当前位置: 首页 > 面试题库 >

是否可以使用GoLang数据库/ SQL按名称检索列值

宋宇
2023-03-14
问题内容

所有的我已经看到了使用实施例sql.Row,获得的返回值,从查询由 位置sql.Rows.scan()需要正确地正确类型的变量
定位scan()对应于相应的列,来检索每个列的值的参数返回,如在下面的例子:

基于GoDocs的示例(带有小型mod):

rows, err := db.Query("SELECT name,age FROM users WHERE age>=50")
if err != nil {
    log.Fatal(err)
}
for rows.Next() {
    var name string
    var age int

    if err := rows.Scan(&name,&age); err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%s is %d\n", name, age)
}
if err := rows.Err(); err != nil {
    log.Fatal(err)
}

&name并且&age必须正确放置Rows.Scan()的位置(0和1列),以检索具有正确类型的正确值。

在生产系统的多年开发中,我一直在避免这种做法,因为这种做法不够可靠:如果数据库的布局基于列位置,则更改列布局会很容易破坏您的代码。

使用 列名 检索值要更健壮-
这样可以使您免受对数据库的更改的影响,这些更改添加或删除了会损坏基于位置的代码的列。例如,在Delphi和C#中,所有的数据集,包括返回从查询,支持值的列FieldByName('age').asIntegerfields['age'].value,

有什么办法可以在Go中做到这一点?如果不是这样,这将是Go数据库支持中的一个很大缺点,并且会令人严重失望-完全不安全,如上所述。

编辑:

另外 (也许这是一个新问题) :我所看到的示例似乎要求您检索查询返回的所有列,否则列的位置将倾斜。

假设在锁定的数据库中存在无法修改或添加的实用程序查询,并且它检索了几列,但是对于当前任务,我只需要其中一列。基于当前sql.Rows.Scan()模型,即使我不需要它们,我也必须从应用程序代码中的查询中检索所有值,而如果我可以查询"columnByName"不必要的值,则可以将我的应用程序代码带入我需要的数据。有任何解决方法吗?


问题答案:

是的,可以这样做,而不必手动匹配列位置。您可以使用一些第三方库来执行此操作,例如sqlx或gorp。我建议坚持使用其中之一,而不要自己动手。

命名匹配确实会有轻微的损失。命名匹配与自己匹配列位置没有什么不同。它只是在运行时为您完成这项工作-可能会在每次查询执行时执行。在任何其他语言中都是如此。

为什么在运行时?查询被写为字符串。必须对其进行分析以确定位置。

如果要创建自己的库,该如何自己做呢?

  • Rows.Columns获取列名和位置。
  • 将切片的指针传递[]interface{}给Rows.Scan以获取值。

  • reflect.Value和Value.Addr获得指向目标值的指针。

  • Value如果要映射到结构字段,则使用Value.FieldByName获取结构字段的。

好的,让我们看看它是如何工作的。

type Person struct {
    Id int
    Name string
}
rows, err := db.Query("SELECT id, name FROM person;")
if err != nil {
    // handle err
    log.Fatal(err)
}
columnNames, err := rows.Columns() // []string{"id", "name"}
if err != nil {
    // handle err
    log.Fatal(err)
}
people = make([]Person, 0, 2)
for rows.Next() {
    person := Person{}
    // person == Person{0, ""}
    pointers := make([]interface{}, len(columnNames))
    // pointers == `[]interface{}{nil, nil}`
    structVal := reflect.ValueOf(person)
    for i, colName := range columnNames {
        fieldVal := structVal.FieldByName(strings.Title(colName))
        if !fieldVal.IsValid() {
            log.Fatal("field not valid")
        }
        pointers[i] = fieldVal.Addr().Interface()
    }
    // pointers == `[]interface{}{&int, &string}`
    err := rows.Scan(pointers...)
    if err != nil {
        // handle err
        log.Fatal(err)
    }
    // person == Person{1, "John Doe"}
    people = append(people, person)
}


 类似资料:
  • 问题内容: 我正在编写一些工具,当对它应用任何查询时,该工具必须检索检索到的数据集的列名。 如果您熟悉phpMyAdmin,您将意识到SQL窗格可以执行查询并显示结果以及列名。我想知道查询会有多困难,它总是产生列名,而幕后的编程实际上是什么?就像它会分析查询,然后从查询中查找表名称,然后首先使用查询检索列名称,然后再检索数据吗? 有什么更好的办法吗? 已更新 对不起,不完整的信息,我想我必须说我在

  • 问题内容: 我有一个看起来像这样的表: 我想获得一个二维表,该表为我提供每个站点月份的“ Val”,例如: 但是要注意的是,我不知道“站点”中所有可能的值。如果出现一个新站点,我想在结果表中自动获得一个新列。 我看到的所有可以做到这一点的代码示例都要求我在查询文本中对“ Microsoft and Google”进行硬编码。 我看到了一个没有,但是基本上是通过列出站点并在其中生成带有这些列名称的查

  • 我知道有可能通过名字得到一个类,使用 是否可以通过名称检索注释?我尝试了这个: 然后将c转换为

  • 问题内容: 如果我有: 如何使用T-SQL获得元素名称“名称”和“内容”的列表? 到目前为止,我得到的最好成绩是: 但是,当然,我无法解决这个问题。 问题答案: 实际上,对不起,我得到的最好的是: 猜猜我回答了我自己的问题…

  • 问题内容: 自从我上次使用1.4.X版本以来,我一直在尝试更新有关J​​ava的知识…我正在尝试使用1.6.0,尤其是Java Persistence API(2.0)。 我设法创建了一个实体类。因为我能够存储和检索数据,所以它正在工作。 但是我无所事事,当我决定用表的列名填充JList时并没有成功… 这是一个简单的类,看起来像: 有没有办法检索列名? 我找到了这个帖子。似乎是一个有效的解决方案,

  • 是否有任何方法可以在数据框中按索引(即整数)选择行,按列名选择列? 我尝试使用loc,但它返回一个错误,我知道iloc只适用于索引。 这是数据帧df的第一行。我愿意选择第一行,名为“Volume”的列,并尝试使用df.loc[0,'Volume']