我有一个循环遍历一个看起来与此类似的表(简化了错误处理以提高可读性):
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)
}
如您所见,我想扫描每一行的字段,以某种方式修改它们并更新数据库。 someFunc
和someOtherFunc
返回的值对于每一行都是不同的,并且无法单独根据其字段的值来确定。
这段代码不起作用,因为数据库在rows
关闭之前一直处于锁定状态(我正在使用mattn's go-sqlite3 driver)。此外,它效率不高,因为每次更新行时数据库都需要执行查询。我知道我可以使用db.Prepare
,然后在完成迭代后执行所有查询,但这会消耗不必要的内存量,并且不会减轻效率问题。
我已经做了一些阅读,似乎游标提供了我正在寻找的功能(我不是SQL专家),我正在使用的SQL的风格(SQLite3)支持它们,但database/sql
确实似乎没有。
database/sql
在迭代过程中是否有更新行的自然方式?
答案 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()
没有关于锁定数据库的错误。