从 Node.js 向 SQL 服务器插入多行
Inserting multiple rows into SQL Server from Node.js
我正在进行一个项目,该项目将从 node.js 程序将一些记录上传到 SQL 服务器。现在,这是我的方法(在异步函数内):
con = await sql.connect(`mssql://${SQL.user}:${SQL.password}@${SQL.server}/${SQL.database}?encrypt=true`);
for (r of RECORDS) {
columns = `([column1], [column2], [column3])`;
values = `(@col1, @col2, @col3)`;
await con
.request()
.input("col1", sql.Int, r.col1)
.input("col2", sql.VarChar, r.col2)
.input("col3", sql.VarChar, r.col3)
.query(`INSERT INTO [dbo].[table1] ${columns} VALUES ${values}`);
}
其中 records 是以下形式的对象数组:
RECORDS = [
{ col1: 1, col2: "asd", col3: "A" },
{ col1: 2, col2: "qwerty", col3: "B" },
// ...
];
这段代码有效,但是,我感觉它根本没有效率。我上传了大约 4k 条记录,大约需要 10 分钟,看起来不太好。
我相信如果我可以创建单个查询 - 而不是将单个插入包装在 for 循环中 - 使用所有记录值它会更快,而且我知道在 SQL:
INSERT INTO table1 (column1, column2, column3) VALUES (1, "asd", "A"), (2, "qwerty", "B"), (...);
但是我无法从节点的 mssql 模块中找到任何关于如何准备参数化输入以在单个事务中执行所有操作的文档。
谁能指导我正确的方向?
提前致谢。
此外,与批量插入非常相似,您可以使用 table 赋值参数。
sql.connect("mssql://${SQL.user}:${SQL.password}@${SQL.server}/${SQL.database}?encrypt=true")
.then(() => {
const table = new sql.Table();
table.columns.add('col1', sql.Int);
table.columns.add('col2', sql.VarChar(20));
table.columns.add('col3', sql.VarChar(20));
// add data
table.rows.add(1, 'asd', 'A');
table.rows.add(2, 'qwerty', 'B');
const request = new sql.Request();
request.input('table1', table);
request.execute('procMyProcedure', function (err, recordsets, returnValue) {
console.dir(JSON.stringify(recordsets[0][0]));
res.end(JSON.stringify(recordsets[0][0]));
});
});
然后对于 SQL 端,创建一个用户定义的 table 类型
CREATE TYPE typeMyType AS TABLE
(
Col1 int,
Col2 varchar(20),
Col3 varchar(20)
)
然后在存储过程中使用这个
CREATE PROCEDURE procMyProcedure
@table1 typeMyType READONLY
AS
BEGIN
INSERT INTO table1 (Col1, Col2, Col3)
SELECT Col1, Col2, Col3
FROM @MyRecords
END
这使您可以更好地控制数据,并让您在实际插入之前对 sql 中的数据执行更多操作。
正如@JoaquinAlvarez 所指出的,批量插入应该按照此处的回复使用:Bulk inserting with Node mssql package
对于我的情况,代码如下:
return await sql.connect(`mssql://${SQL.user}:${SQL.password}@${SQL.server}/${SQL.database}?encrypt=true`).then(() => {
table = new sql.Table("table1");
table.create = true;
table.columns.add("column1", sql.Int, { nullable: false });
table.columns.add("column2", sql.VarChar, { length: Infinity, nullable: true });
table.columns.add("column3", sql.VarChar(250), { nullable: true });
// add here rows to insert into the table
for (r of RECORDS) {
table.rows.add(r.col1, r.col2, r.col3);
}
return new sql.Request().bulk(table);
});
SQL 数据类型必须(显然)匹配现有 table table1
的列类型。请注意 column2 的情况,它是在 SQL 中定义为 varchar(max) 的列。
谢谢华金!我的时间从 10 分钟显着减少到几秒钟
我正在进行一个项目,该项目将从 node.js 程序将一些记录上传到 SQL 服务器。现在,这是我的方法(在异步函数内):
con = await sql.connect(`mssql://${SQL.user}:${SQL.password}@${SQL.server}/${SQL.database}?encrypt=true`);
for (r of RECORDS) {
columns = `([column1], [column2], [column3])`;
values = `(@col1, @col2, @col3)`;
await con
.request()
.input("col1", sql.Int, r.col1)
.input("col2", sql.VarChar, r.col2)
.input("col3", sql.VarChar, r.col3)
.query(`INSERT INTO [dbo].[table1] ${columns} VALUES ${values}`);
}
其中 records 是以下形式的对象数组:
RECORDS = [
{ col1: 1, col2: "asd", col3: "A" },
{ col1: 2, col2: "qwerty", col3: "B" },
// ...
];
这段代码有效,但是,我感觉它根本没有效率。我上传了大约 4k 条记录,大约需要 10 分钟,看起来不太好。
我相信如果我可以创建单个查询 - 而不是将单个插入包装在 for 循环中 - 使用所有记录值它会更快,而且我知道在 SQL:
INSERT INTO table1 (column1, column2, column3) VALUES (1, "asd", "A"), (2, "qwerty", "B"), (...);
但是我无法从节点的 mssql 模块中找到任何关于如何准备参数化输入以在单个事务中执行所有操作的文档。
谁能指导我正确的方向?
提前致谢。
此外,与批量插入非常相似,您可以使用 table 赋值参数。
sql.connect("mssql://${SQL.user}:${SQL.password}@${SQL.server}/${SQL.database}?encrypt=true")
.then(() => {
const table = new sql.Table();
table.columns.add('col1', sql.Int);
table.columns.add('col2', sql.VarChar(20));
table.columns.add('col3', sql.VarChar(20));
// add data
table.rows.add(1, 'asd', 'A');
table.rows.add(2, 'qwerty', 'B');
const request = new sql.Request();
request.input('table1', table);
request.execute('procMyProcedure', function (err, recordsets, returnValue) {
console.dir(JSON.stringify(recordsets[0][0]));
res.end(JSON.stringify(recordsets[0][0]));
});
});
然后对于 SQL 端,创建一个用户定义的 table 类型
CREATE TYPE typeMyType AS TABLE
(
Col1 int,
Col2 varchar(20),
Col3 varchar(20)
)
然后在存储过程中使用这个
CREATE PROCEDURE procMyProcedure
@table1 typeMyType READONLY
AS
BEGIN
INSERT INTO table1 (Col1, Col2, Col3)
SELECT Col1, Col2, Col3
FROM @MyRecords
END
这使您可以更好地控制数据,并让您在实际插入之前对 sql 中的数据执行更多操作。
正如@JoaquinAlvarez 所指出的,批量插入应该按照此处的回复使用:Bulk inserting with Node mssql package
对于我的情况,代码如下:
return await sql.connect(`mssql://${SQL.user}:${SQL.password}@${SQL.server}/${SQL.database}?encrypt=true`).then(() => {
table = new sql.Table("table1");
table.create = true;
table.columns.add("column1", sql.Int, { nullable: false });
table.columns.add("column2", sql.VarChar, { length: Infinity, nullable: true });
table.columns.add("column3", sql.VarChar(250), { nullable: true });
// add here rows to insert into the table
for (r of RECORDS) {
table.rows.add(r.col1, r.col2, r.col3);
}
return new sql.Request().bulk(table);
});
SQL 数据类型必须(显然)匹配现有 table table1
的列类型。请注意 column2 的情况,它是在 SQL 中定义为 varchar(max) 的列。
谢谢华金!我的时间从 10 分钟显着减少到几秒钟