在Node和sqlite3中插入多行多列

问题描述 投票:0回答:3

我正在尝试使用单个操作将许多不同的行插入到 sqlite 数据库中。每行都有多个列,我将数据表示为数组的数组。

我已阅读用户指南和其他教程,但所有提到插入多行的教程都适用于仅具有单列的行。

我正在尝试插入一个更大的数组,但为了测试它,我将其分解为两个条目。

let testArtist = [["string", 1, 2, "string"], ["string", 3, 4, "string"]];
let artistQuery = "INSERT INTO artists (artist, numSongs, numAlbums, picture) VALUES (?, ?, ?, ?), (?, ?, ?, ?)";

db.serialize(
    db.run(artistQuery, [testArtist], function(err){
        if(err) throw err;
    });
});

这是插入操作的结果

select * from artists;
1||||
2||||

因此正在插入

AUTOINCREMENT
整数 ID,但没有插入数据。

node.js sqlite node-sqlite3
3个回答
8
投票

编辑:我自己想出来了,伙计们。您需要做的是将数组展平为单个数组。

所以:

[["string", 1, 2, "string"], ["string", 3, 4, "string"]]

变成:

["string, 1, 2, "string", "string", 3, 4, "string"]

您仍然需要分隔

INSERT INTO
操作中的值,我为此使用了
map
函数,如教程中所述。

let artistPlaceholders = artistRecords.map(() => "(?, ?, ?, ?)").join(', ');
let artistQuery = "INSERT INTO artists (artist, numSongs, numAlbums, picture) VALUES " + artistPlaceholders;
let flatArtist = [];
artistRecords.forEach((arr) => { arr.forEach((item) => { flatArtist.push(item) }) });

db.serialize(function(){
    db.run(artistQuery, flatArtist, function(err){
        if(err) throw err;
    });
});

其中

artistRecords
是一个数组,其形式为:

[["string", 0, 0, "string"], ["string", 0, 0, "string"], [...]]

如果您有一个具有多层嵌套的数组,则需要修改展平函数。


7
投票

我想 @Chris 自己的答案是在一个巨大的 INSERT 语句中完成多行和多列的唯一方法(尽管我有兴趣听听为什么它只需要一个操作)。

我也很难在 node.js 中找到 sqlite3 的示例(这就是我最终到达这里的原因),因此我想分享一个多列示例,该示例可以实现上述目标,但需要进行多个操作。

let testArtist = [
   ["string", 1, 2, "string"],
   ["string", 3, 4, "string"]
];

// create the statement for the insertion of just ONE record
let artistQuery = 
   "INSERT INTO artists (artist, numSongs, numAlbums, picture) " +
   "VALUES (?, ?, ? ,?)"; 

// 'prepare' returns a 'statement' object which allows us to 
// bind the same query to different parameters each time we run it
let statement = db.prepare(artistQuery);

// run the query over and over for each inner array
for (var i = 0; i < testArtist.length; i++) {
    statement.run(testArtist[i], function (err) { 
        if (err) throw err;
    });
}

// 'finalize' basically kills our ability to call .run(...) on the 'statement'
// object again. Optional.
statement.finalize();

// If I call statement.run( ... ) here again, I will get an error due 
// to the 'finalize' call above.

如果您需要保证所有行都按顺序插入,您可以像 @Chris 那样将整个循环包装在

db.serialize( ... )
中。


0
投票

我试图批量插入到多对多表中,但有些记录无法插入。没有一个错误。根据之前的回复,这就是我得到的:

    //I'm using typescript to run node
    const permissionIds: number[] = [1,2,3]; //hardcoded for the example, populate as you need
    const roleId = 10; //hardcoded

    const placeholders = permissionIds.map(() => '(?, ?)').join(',');
    const insertSql = `INSERT INTO roles_permissions (role, permission) VALUES ${placeholders}`;

    const rolePermissionValues = permissionIds.flatMap((permissionId) => [roleId, permissionId]);

    this.db.serialize(() => {
        this.db.run(insertSql, rolePermissionValues, (err) => {
            if (err) {
                console.error(err.message);
            }
        })
    });
© www.soinside.com 2019 - 2024. All rights reserved.