PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Inserção de várias linhas com pg-promise


Eu sou o autor de pg-promise.

Nas versões mais antigas da biblioteca, isso era coberto por exemplos simplificados no artigo Performance Boost, que ainda é uma boa leitura ao escrever aplicativos de banco de dados de alto desempenho.

A abordagem mais recente é contar com o namespace helpers, que é flexível e otimizado para desempenho.
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);

Consulte API:ColumnSet, inserir.

Essa inserção nem mesmo requer uma transação, porque se um conjunto de valores não for inserido, nenhum será inserido.

E você pode usar a mesma abordagem para gerar qualquer uma das seguintes consultas:
  • linha única INSERT
  • INSERT de várias linhas
  • UPDATE de linha única
  • UPDATE de várias linhas

As inserções usando a notação ${} são protegidas contra injeção de sql?

Sim, mas não sozinho. Se você estiver inserindo nomes de esquema/tabela/coluna dinamicamente, é importante usar nomes SQL, que em combinação protegerão seu código contra injeção de SQL.

Pergunta relacionada:atualizações de várias linhas do PostgreSQL no Node.js

extras


P:Como obter o id de cada novo registro ao mesmo tempo?

R: Simplesmente anexando RETURNING id para sua consulta e executando-a com o método many:
const query = pgp.helpers.insert(values, cs) + ' RETURNING id';
    
const res = await db.many(query);
//=> [{id: 1}, {id: 2}, ...]

ou melhor ainda, pegue o id-s e converta o resultado em array de inteiros, usando o método map:
const res = await db.map(query, undefined, a => +a.id);
//=> [1, 2, ...]

Para entender por que usamos + lá, veja:pg-promise retorna inteiros como strings.

ATUALIZAÇÃO-1

Para inserir um grande número de registros, consulte Importações de dados.

ATUALIZAÇÃO-2

Usando a v8.2.1 e posterior, você pode agrupar a geração de consulta estática em uma função, para que ela possa ser gerada dentro do método de consulta, para rejeitar quando a geração de consulta falhar:
// 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);