我正在尝试插入一些依赖于先前查询数据的数据,我将查询和插入序列化,但我无法获得正确的结果。
我构建这个简单的例子来显示我的错误。它只查询表中的行数,并将其插回到表中。
db.serialize(function() {
var count=0;
db.each("SELECT count(rowid) FROM info", function(err, row) {
count = row['count(rowid)'];
});
var stmt = db.prepare("INSERT INTO info VALUES (?)");
stmt.run('Lorem ipsum '+(count+1));
stmt.finalize();
});
如果我运行此代码三次并检查数据,我只需获得字符串" Lorem ipsum 1" 三次。
此外,如果我在stmt.finalize
指令后添加一些查询代码
db.each("SELECT count(rowid) FROM info", function(err, row) {
count = row['count(rowid)'];
console.log('count info',count);
});
db.each("SELECT rowid AS id, info FROM info", function(err, row) {
console.log(row.id + ": " + row.info)
});
查询序列化正确并且我得到了预期的计数但仍然是错误的插入(在示例中我运行了插入代码五次)
count info 5
1: Lorem ipsum 1
2: Lorem ipsum 1
3: Lorem ipsum 1
4: Lorem ipsum 1
5: Lorem ipsum 1
你能解释db.prepare()
的这种行为吗?你能提出更正吗?
答案 0 :(得分:1)
这是一个古老的问题,但是由于我也遇到了同样的问题,并在数年后浏览了此页面,所以我认为我会刺痛我的理解:
db.serialize将序列化查询。这意味着,如果有一个查询在运行,其他查询将排队等待稍后再运行,因此您可以确保查询按显示顺序运行。但这并不意味着JS代码本身已被阻止。您的代码假定db.serialize导致数据库调用被阻塞(同步)。我相信问题出在这里:
var count=0;
[...]
var stmt = db.prepare("INSERT INTO info VALUES (?)");
stmt.run('Lorem ipsum '+(count+1));
具体地说,第二条语句将在上一条语句之后排队等待运行。但是,尽管该声明是正确的,但已经发生了对( count + 1 )的评估。这意味着 count 被初始化为0,运行了(缓慢的)数据库查询,并且使用 count + 1 将一条语句排队。由于 count + 1 的计算没有等待查询完成,因此使用了 count 的原始值( 0 ),并且您正在有效排队:
INSERT INTO info VALUES ('Lorem ipsum ' + (0 + 1))
这说明了为什么您总是看到“ Lorem ipsum 1”。
我相信解决此问题的方法是在第二条sql语句的第一个回调中排队。只有这样,您才能放心计数将正确更新。
当然,另一个解决方法是构造一个INSERT语句,该语句使用SQL直接计算计数,但是我假设您创建了这个人工示例来证明这一点。
调味
答案 1 :(得分:0)
我不确定2个月后这个答案仍然有用。
首先插入“'Lorem ipsum'+(count + 1)”我们需要迭代。
其次SQL查询需要返回列。
db.serialize(function() {
db.run("CREATE TABLE IF NOT EXISTS info (info TEXT)");
var stmt = db.prepare("INSERT INTO info VALUES (?)");
for (i = 0 ; i < 5 ; i++) { // an iteration is required to insert data into the table
stmt.run('Lorem ipsum '+ i);
}
stmt.finalize();
db.each("SELECT rowid AS id, info FROM info", function(err, row) { // columns should be retrieved
console.log(row.id + ": " + row.info);
});
});
有关详细信息,请参阅docs