如何在sqlite3和nodejs中顺序迭代行?

2mbi3lxu  于 2023-01-09  发布在  SQLite
关注(0)|答案(1)|浏览(178)

bounty将在5天后过期。回答此问题可获得+50的声誉奖励。John正在寻找来自声誉良好来源的答案:我不想使用非异步休眠挂起主循环或修改sqlite库

我想同步迭代sqlite数据库,在db.each()中使用asyncsleep不会延迟每个回调,因为它不会在内部回调中使用wait:

var sleep = require("sleep");
var sqlite3 = require("sqlite3");
sqlite3.verbose();
var sqlite = require("sqlite");

(async () =>
{
    var db = await sqlite.open({
        filename: "./mydatabase.db",
        driver: sqlite3.Database
    });

    // doesn't await this async callback before calling the next
    // row result function 
    await db.each(`SELECT * FROM mytable`, async (err, row) =>
    {
        await sleep(10000);
        
        console.log(row);
    });
})();

我不想使用.all(),因为将数十万条记录加载到内存中需要很长时间。
我也不想使用LIMIT x OFFSET y,因为它需要对每个要检查的部分多次重新运行查询,这会使查询速度变慢。
如何同步迭代sqlite结果,以便在处理完当前行之前不读取下一行?
在PHP中,它类似于以下类型的循环:

// fetches one result at a time and does not continue until
// I call the next `mysql_fetch_row`
while(($row = mysql_fetch_row($queryResult))
{
    var_dump($row);
    sleep(123);
}

我希望一次只得到一个结果,而不是被成千上万个不停调用的回调函数淹没。

amrnrhlw

amrnrhlw1#

这是当前对sqlite库的功能请求。
你可以在这里看到它:https://github.com/kriasoft/node-sqlite/issues/127
You can see examples how to achieve that like AlttiRi's answer: https://github.com/kriasoft/node-sqlite/issues/127#issuecomment-794317769
但我的建议和@Rick Suggs一样,您最好使用更好的sqlite3:https://www.npmjs.com/package/better-sqlite3
它是为使用async/await语法而从头设计的。
它就像PHP一样简单明了

const stmt = db.prepare('SELECT * FROM cats');

for (const cat of stmt.iterate()) {
  if (cat.name === 'Joey') {
    console.log('found him!');
    break;
  }
}

Here is the full documentation: https://github.com/WiseLibs/better-sqlite3/blob/HEAD/docs/api.md#iteratebindparameters---iterator
下面是一个完整的示例,您可以如何实现这一点:

const Database = require("better-sqlite3");
const db = new Database("mydatabase.db", { verbose: console.log });

const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

(async () => {

    // Execute only the first time to create table with data
    // await db.exec("CREATE TABLE myTable (col TEXT)");
    // await db.exec('INSERT INTO myTable VALUES ("test")');
    // await db.exec('INSERT INTO myTable VALUES ("test2")');

    const stmt = db.prepare("SELECT * FROM myTable");

    for (const row of stmt.iterate()) {
        await sleep(3000);
        console.log(row);
    }
})();

输出为:

// 3 seconds delay
{ col: 'test' }
// 3 seconds delay
{ col: 'test2' }

相关问题