golang中的sql事务中的批量upsert

时间:2014-08-13 15:00:18

标签: sql transactions go bulkinsert upsert

我一直在使用golang的sql包进行交易,我试图了解如何在没有" per insert"的情况下进行批量upsert。每行的往返通信。 examples here并未真正显示批量查询的完成方式。

updateMoney, err := db.Prepare("INSERT INTO balance set money=?, id=? ON DUPLICATE UPDATE balance SET money=money+? WHERE id=?")
...
tx, err := db.Begin()
...
res, err := tx.Stmt(updateMoney).Exec(123.45, 1, 123.45, 1)
res, err := tx.Stmt(updateMoney).Exec(67.89, 2, 67.89, 2)
res, err := tx.Stmt(updateMoney).Exec(10.23, 3, 10.23, 3)
...
tx.Commit()

理想情况下,我能够进行准备好的查询,并建立一个同时发送的upsert列表......但是在这里,我们在每次执行后从数据库中得到一个结果。关于如何解决这个问题的任何建议?

编辑: 我的同事发现this open ticket描述了这个问题......它看起来比一个事务的背景下更严重。

2 个答案:

答案 0 :(得分:7)

这取决于您使用的驱动程序,某些驱动程序/数据库根本不支持事务。

例如go-sql-driver/mysql支持交易就好了。

您的代码应该可以使用,或者您可以将其更改为:

tx, err := db.Begin()
...
stmt, err := tx.Prepare(`INSERT INTO balance set money=?, id=? ON DUPLICATE UPDATE balance SET money=money+? WHERE id=?`)
res, err := stmt.Exec(123.45, 1, 123.45, 1)
res, err := stmt.Exec(67.89, 2, 67.89, 2)
res, err := stmt.Exec(10.23, 3, 10.23, 3)
...
tx.Commit()

另请查看此answer,其中包含有关交易的大量详细信息。

答案 1 :(得分:3)

因此,虽然我们无法对每个upsert执行单独的查询,但我们在单个语句中为批量upsert编写了有效的mysql ...

INSERT INTO balance (id, money) VALUES (1, 123.45), (2, 67.89), (3, 10.23)
ON DUPLICATE KEY UPDATE money = money + values(money)

因此对于任何想要进行批量upsert的人来说,有一种模式可以解决mysql驱动程序的任何限制。