带有 pg-promise 的多行插入 [英] Multi-row insert with pg-promise

查看:36
本文介绍了带有 pg-promise 的多行插入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I would like to insert multiple rows with a single INSERT query, for example:

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

有没有一种方法可以轻松做到这一点,最好是针对这样的对象数组:

Is there a way to do this easily, preferably for an array of objects like these:

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

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

I might end up with 500 records in one chunk, so running multiple queries would be undesirable.

到目前为止,我只能为单个对象执行此操作:

So far I have been able to do it for a single object only:

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

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

As a side question: Are insertions using ${} notation protected against SQL injections?

推荐答案

我是 的作者pg-承诺.

在旧版本的库中,中的简化示例涵盖了这一点Performance Boost 文章,在编写高性能数据库应用程序时仍然值得一读.

In older versions of the library this was covered by simplified examples within the Performance Boost article, which is still a good read when writing high-performance database applications.

较新的方法是依赖 helpers 命名空间,它最终是灵活的,并针对性能进行了优化.

The newer approach is to rely on the helpers namespace, which is ultimately flexible, and optimised for performance.

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:ColumnSet插入.

这种插​​入甚至不需要事务,因为如果一组值插入失败,则不会插入.

Such an insert doesn't even require a transaction, because if one set of values fails to insert, none will insert.

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

And you can use the same approach to generate any of the following queries:

  • 单行INSERT
  • 多行INSERT
  • 单行UPDATE
  • 多行UPDATE

使用 ${} 符号的插入是否可以防止 sql 注入?

Are insertions using ${} notation protected against sql injection?

是的,但并不孤单.如果您要动态插入架构/表/列名称,请务必使用 SQL 名称,结合起来可以保护您的代码免受 SQL 注入.

Yes, but not alone. If you are inserting schema/table/column names dynamically, it is important to use SQL Names, which in combination will protect your code from SQL injection.

相关问题:PostgreSQL 在 Node.js 中的多行更新.js

问:如何同时获取每条新记录的id?

A: 只需将 RETURNING id 附加到您的查询中,然后使用 很多:

A: Simply by appending RETURNING id to your query, and executing it with method many:

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

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

or even better, get the id-s, and convert the result into array of integers, using method map:

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

要了解我们为什么在那里使用 +,请参阅:pg-promise 以字符串形式返回整数.

To understand why we used + there, see: pg-promise returns integers as strings.

UPDATE-1

要插入大量记录,请参阅数据导入.

For inserting huge number of records, see Data Imports.

UPDATE-2

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

Using v8.2.1 and later, you can wrap the static query-generation into a function, so it can be generated within the query method, to reject when the query generation fails:

// 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);

这篇关于带有 pg-promise 的多行插入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆