如何在nodejs sqlite3中正确序列化db.prepare

时间:2016-10-21 10:37:37

标签: node.js sqlite

我正在尝试插入一些依赖于先前查询数据的数据,我将查询和插入序列化,但我无法获得正确的结果。

我构建这个简单的例子来显示我的错误。它只查询表中的行数,并将其插回到表中。

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()的这种行为吗?你能提出更正吗?

2 个答案:

答案 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