我正在尝试使用node-sqlite3从我的node.js应用程序在数据库中执行INSERT + UPDATE事务。但是,我无法弄清楚如何在事务完成时获取last_insert_rowid。我的查询看起来像这样:
BEGIN TRANSACTION;
INSERT INTO <table> (field1, ...) VALUES (value1, ...);
UPDATE <table> SET prev=last_insert_rowid() WHERE <condition>;
END TRANSACTION;
此字符串(减去额外的空格)分配给var q
。
我已经在某个时候打开了我的数据库:
var db = new sqlite3.Database(dbfile)
但如果我尝试使用:
db.run(q, function(err) {
if (err) ...
console.log(this.lastId)
})
它不仅没有错误地打印“0”,而且没有对数据库进行任何更改!如果我使用exec
而不是run
,则查询会成功运行,但我无法从exec获取任何数据。
我也尝试过这样的事情:
db.exec(q, function(err) {
if (err) ...
db.run(";", function(err) {
if (err) ...
console.log(this.lastId)
})
})
但是“run”上的“this”上下文没有lastId属性!
我也查看了sqlite3-transaction包,但它似乎也没有在事务回调中提供任何信息!
我无法将插件作为单独的run()运行,获取this.lastId
然后使用它来运行更新,因为这会使数据库在两个语句之间处于无效状态(因此需要交易)。
如何从此交易中获取last_insert_rowid()?
答案 0 :(得分:0)
为了获取last_insert_rowid(),有必要将事务分解为多个部分,如下所示。首先,运行查询以开始事务:
db.run("BEGIN TRANSACTION")
接下来,运行命令插入行,在回调中获取rowid:
// replace stuff in angle brackets and ellipses with proper values
db.run("INSERT INTO <table> (field1, ...) VALUES (value1, ...);", function(err,data) {
if (err) ...
rowid=this.lastID // rowid declared in scope visible outside callback
})
接下来,运行更新。由于交易尚未提交,因此尚未调用这些回调。
db.run("UPDATE <table> SET prev=last_insert_rowid() WHERE <condition>;", function(err,data) {
// do whatever needs doing after update is done here
})
现在提交交易:
db.run("END TRANSACTION;")
在这种情况下,由于更新是事务中的最后一个语句,如果成功,整个事务应该成功,那么在该地点的事务之后做任何事情都应该是安全的。