小编典典

Golang的SQL程序包不能进行临时/探索性查询吗?

go

根据文档,在Go中从数据库中获取数据的唯一方法似乎是使用Rows.Scan(),这意味着您必须在编译时知道所有列的数量和类型。

我想念什么吗?您应该如何支持即席查询?甚至将所有列从将来可能更改的表中拉出来?


阅读 243

收藏
2020-07-02

共1个答案

小编典典

sql.Rows类型具有Columns可以为您提供结果列名称列表的方法。可以用来确定未知查询的列数。

在该Scan方法的文档中,它说:

如果参数的类型为 [] byte,则Scan会将相应数据的副本保存在该参数中。该副本归调用方所有,可以无限期修改和保存。可以通过使用
RawBytes类型的参数来避免复制。有关其使用限制,请参见RawBytes文档。

如果参数的类型为* interface {},则Scan会复制基础驱动程序提供的值,而无需进行转换。如果该值的类型为[]
byte,则进行复制,并且调用方拥有结果。

因此,当我们不知道列值的类型时(原始格式或Go类型),我们也支持扫描列值。

将这两者放在一起,您可以使用...语法调用可变参数函数来执行以下操作:

columnNames, err := rows.Columns()
if err != nil {
    log.Fatalln(err) // or whatever error handling is appropriate
}
columns := make([]interface{}, len(columnNames))
columnPointers := make([]interface{}, len(columnNames))
for i := 0; i < len(columnNames); i++ {
    columnPointers[i] = &columns[i]
}
if err := rows.Scan(columnPointers...); err != nil {
    log.Fatalln(err)
}

现在,columns切片应包含当前结果行的所有列值的解码版本。

如果您对表格有额外的了解(例如,预期的类型,或者提前知道列数),则可以稍微简化一下逻辑。

2020-07-02