如何在迭代行中修改行

时间:2017-04-27 14:49:50

标签: sql go sqlite

我有一个循环遍历一个看起来与此类似的表(简化了错误处理以提高可读性):

for rows.Next() {
    var (
        id          int
        field2      int
        field1      int
    )
    err = rows.Scan(&id, &field1, &field2)
    chk(err)
    field1 += someFunc()
    field2 += someOtherFunc()
    err = db.Exec(`UPDATE table SET field1 = ?, field2 = ? WHERE id = ?`, field1, field2, id)
    chk(err)
}

如您所见,我想扫描每一行的字段,以某种方式修改它们并更新数据库。 someFuncsomeOtherFunc返回的值对于每一行都是不同的,并且无法单独根据其字段的值来确定。

这段代码不起作用,因为数据库在rows关闭之前一直处于锁定状态(我正在使用mattn's go-sqlite3 driver)。此外,它效率不高,因为每次更新行时数据库都需要执行查询。我知道我可以使用db.Prepare,然后在完成迭代后执行所有查询,但这会消耗不必要的内存量,并且不会减轻效率问题。 我已经做了一些阅读,似乎游标提供了我正在寻找的功能(我不是SQL专家),我正在使用的SQL的风格(SQLite3)支持它们,但database/sql确实似乎没有。

database/sql在迭代过程中是否有更新行的自然方式?

1 个答案:

答案 0 :(得分:0)

你应该执行你的SELECT&针对事务的更新,而不是句柄。我在其中一个项目中偶然发现了它,现在有了这样的代码:

tx, err := dbh.Begin()
...
rows1, err := tx.Query("SELECT id, data FROM cache")
...
for rows1.Next() {
...
   tx.Exec("DELETE FROM cache WHERE id = ?", id)
...
}
tx.Commit()

没有关于锁定数据库的错误。