gpt4 book ai didi

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

转载 作者:IT老高 更新时间:2023-10-28 13:08:57 25 4
gpt4 key购买 nike

我见过的所有使用 sql.Row 的示例,通过 position 访问查询的返回值:sql.Rows.scan() 需要在对应于相应列的 scan() 参数中正确定位 类型正确的变量,以检索返回的每个列值,如下例所示:

Example Based on GoDocs (with small 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 必须正确定位(第 0 列和第 1 列),Rows.Scan() 才能检索具有正确类型的正确值。

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

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

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

编辑:

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

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

最佳答案

是的,无需手动匹配列位置即可执行此操作。您可以使用一些第三方库来执行此操作,例如 sqlxgorp .我建议坚持使用其中之一,而不是自己动手。

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

为什么在运行时?查询以字符串形式编写。必须对其进行解析才能确定位置。

如果您要制作自己的库,您如何自己做呢?

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

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)
}

关于sql - 是否可以使用 GoLang 数据库/sql 按名称检索列值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21986780/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com