我看到的所有使用sql.Row
的例子,都是通过position从查询中访问返回值: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
必须正确定位(第0列和第1列),才能使用正确的类型检索正确的值。
在我多年的生产系统开发过程中,我一直在刻意避免这种做法,因为它不健壮:如果数据库对列布局的更改是基于列位置的,那么它很容易破坏代码。
使用列名来检索值要健壮得多--这将使您避免对数据库进行更改,这些更改会添加或删除列,从而破坏基于位置的代码。例如,在 Delphi 和C#中,所有数据集,包括从查询返回值的列,都支持FieldByName('age').asInteger
或fields['age'].value,
等。
在Go中有什么方法可以做到这一点吗?如果没有,这是Go数据库支持的一个很大的缺点,也是一个严重的失望--一点也不安全。
编辑:
- (这可能是一个新问题)*:我所看到的示例似乎要求您检索查询返回的所有列,否则列的位置将发生偏移。
假设在一个锁定的数据库中有一个实用程序查询,我不能修改或添加它,它检索几个列,但我只需要其中一个列来完成当前任务。基于当前的sql.Rows.Scan()
模型,我必须从应用程序代码中的查询中检索所有值,即使我不需要它们,而如果我可以查询"columnByName"
,那就没有必要了-我可以直接将所需的数据带入应用程序代码。对此有什么变通办法吗?
3条答案
按热度按时间ep6jt1vc1#
是的,可以这样做,而不必手动匹配列位置。您可以使用一些第三方库来完成此操作,例如sqlx或gorp。我会建议坚持其中之一,而不是滚动自己的。
命名匹配确实有轻微的惩罚。命名匹配与自己匹配列位置没有什么不同。它只是在运行时为您完成这项工作-可能在每次查询执行时。这在任何其他语言中都是正确的。
为什么是runtime?查询被写成字符串。它必须被解析以确定位置。
如果你想建立自己的图书馆,你怎么做?
[]interface{}
的一个片段传递给Rows。扫描以获取值。Value
。好吧,让我们看看这是如何工作的。
ktca8awb2#
唯一明智和干净的方法是用途:https://github.com/jmoiron/sqlx
假设你有一个Place结构:
你可以轻松地扫描它:
更多信息:http://jmoiron.github.io/sqlx/
qij5mzcb3#
也许对数据采取不同的方法会有所帮助,就像这样: