我想用一个INSERT查询插入多行,例如:

INSERT INTO tmp(col_a,col_b) VALUES('a1','b1'),('a2','b2')...

有没有一种方法可以很容易地做到这一点,最好是针对这样的一系列对象:

[{col_a:'a1',col_b:'b1'},{col_a:'a2',col_b:'b2'}]

我可能会在一个块中得到500条记录,因此运行多个查询是不可取的.

到目前为止,我只能为一个物体做这件事:

INSERT INTO tmp(col_a,col_b) VALUES(${col_a},${col_b})

作为一个附带问题:使用${}符号的插入是否可以防止SQL注入?

推荐答案

我是《pg-promise》的作者.

在旧版本的库中,Performance Boost篇文章中的简化示例介绍了这一点,在编写高性能数据库应用程序时,这仍然是一本不错的读物.

较新的方法是依靠helpers namespace,这最终是灵活的,并优化了性能.

const pgp = require('pg-promise')({
    /* initialization options */
    capSQL: true // capitalize all generated SQL
});
const db = pgp(/*connection*/);
    
// our set of columns, to be created only once (statically), and then reused,
// to let it cache up its formatting templates for high performance:
const cs = new pgp.helpers.ColumnSet(['col_a', 'col_b'], {table: 'tmp'});
    
// data input values:
const values = [{col_a: 'a1', col_b: 'b1'}, {col_a: 'a2', col_b: 'b2'}];
    
// generating a multi-row insert query:
const query = pgp.helpers.insert(values, cs);
//=> INSERT INTO "tmp"("col_a","col_b") VALUES('a1','b1'),('a2','b2')
    
// executing the query:
await db.none(query);

见API:ColumnSetinsert.

这样的插入甚至不需要事务,因为如果一组值插入失败,则不会插入任何值.

您可以使用相同的方法生成以下任何查询:

  • 单列INSERT
  • 多排INSERT
  • 单列UPDATE
  • 多排UPDATE

使用${}符号的插入是否受到sql注入的保护?

是的,但不是独自一人.如果您要动态插入模式/表/列名,那么使用SQL Names非常重要,这将保护您的代码不受SQL注入的影响.


相关问题:PostgreSQL multi-row updates in Node.js


extras

Q: How to get 100 of each new record at the same time?

A:只需将RETURNING id添加到查询中,并使用方法many执行即可:

const query = pgp.helpers.insert(values, cs) + ' RETURNING id';
    
const res = await db.many(query);
//=> [{id: 1}, {id: 2}, ...]

或者更好的方法是,获取id-s,并使用方法map将结果转换为整数数组:

const res = await db.map(query, undefined, a => +a.id);
//=> [1, 2, ...]

要了解我们为什么在那里使用+,请参见:pg-promise returns integers as strings.

UPDATE-1

有关插入大量记录的信息,请参见Data Imports.

UPDATE-2

使用v8.2.1及更高版本,您可以将静态查询生成包装到一个函数中,这样就可以在查询方法中生成,以便在查询生成失败时拒绝:

// generating a multi-row insert query inside a function:
const query = () => pgp.helpers.insert(values, cs);
//=> INSERT INTO "tmp"("col_a","col_b") VALUES('a1','b1'),('a2','b2')
    
// executing the query as a function that generates the query:
await db.none(query);

Node.js相关问答推荐

链接Inbox类方法,范围在哪里以及为什么发生变化?

Stripe webhook无法访问Express请求原始正文

如何将我的Redis客户端配置为在禁用群集模式的情况下使用读取副本?

如何防止Socket-io实例化React/Next.js中的两个套接字(当前在服务器*和*客户端实例化)

如何在医学中按patientId查找一个并同时插入多个数据

当变量在另一个文件中初始化时,在初始化错误之前无法访问变量

在对象的嵌套数组中使用$lookup,创建多个记录作为响应,mongodb

为什么 Cors 在 NodeJS 中不起作用

如何使用包含条件正确分页的 sequelize 查询?

在 .htaccess 中从非 www 切换到 www 后如何解决无法访问该站点?

Node.js 上的 CLI 应用程序如何通过 child_process 将选项值作为参数传递给 Shell 命令

Zod 模式中的self 数组

如何在不使用位置运算符 $ 的情况下更新 mongodb 文档中数组中的嵌套文档?

NestJS TypeORM 可选查询不起作用

Node.js 表达的 Error 对象expose 了哪些属性?

Puppeteer 错误:未下载 Chromium 修订版

如何在 node 调试器中禁用第一行中断

mongoose 模式中的嵌套对象

运行摩卡+伊斯坦布尔+通天塔

如何判断 Node.js 中是否设置了环境变量?