transaction node initoptions example node.js postgresql pg-promise

node.js - node - Inserto de varias filas con pg-promise



pg-promise transaction example (1)

Soy el autor de pg-promise .

En versiones anteriores de la biblioteca, esto estaba cubierto por ejemplos simplificados en el artículo Performance Boost , que sigue siendo una lectura importante al escribir aplicaciones de bases de datos de alto rendimiento.

El enfoque más nuevo es confiar en el espacio de nombres de los asistentes , que en última instancia es flexible y altamente optimizado para el rendimiento.

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, and then shared/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: db.none(query) .then(data => { // success; }) .catch(error => { // error; });

Ver API: ColumnSet , insert .

Tal inserción ni siquiera requiere una transacción, porque si un conjunto de valores no se inserta, ninguno se insertará.

Y puede usar el mismo enfoque para generar cualquiera de las siguientes consultas:

  • INSERT hilera
  • INSERT varias filas
  • UPDATE sola fila
  • UPDATE varias filas

¿Las inserciones que usan la notación $ {} están protegidas contra la inyección sql?

Si, pero no solo. Si está insertando dinámicamente nombres de esquema / tabla / columna, es importante usar nombres SQL , que en combinación protegerán su código de la inyección SQL.

Pregunta relacionada: actualizaciones de varias filas de PostgreSQL en Node.js

extras

P: ¿Cómo obtener la id de cada nuevo registro al mismo tiempo?

R: Simplemente agregando RETURNING id a su consulta y ejecutándolo con el método many :

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

o incluso mejor, obtenga los id-s y convierta el resultado en una matriz de enteros, utilizando el método map :

db.map(query, [], a => +a.id) .then(data => { // data = [1, 2, ...] }) .catch(error => { // error; });

Para entender por qué usamos + allí, vea: pg-promise devuelve enteros como cadenas .

ACTUALIZACIÓN-1

Para insertar una gran cantidad de registros, vea Importaciones de datos .

ACTUALIZACIÓN-2

Con v8.2.1 y versiones posteriores, puede ajustar la generación de consultas estáticas en una función, para que pueda generarse dentro del método de consulta, para rechazar cuando la generación de consultas falla:

// 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: db.none(query) .then(data => { // success; }) .catch(error => { // error; // will get here, even if the query generation fails });

Me gustaría insertar varias filas con una sola consulta INSERT , por ejemplo:

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

¿Hay alguna manera de hacer esto fácilmente, preferiblemente para una variedad de objetos como estos:

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

Podría terminar con 500 registros en un fragmento, por lo que ejecutar múltiples consultas no sería deseable.

Hasta ahora he podido hacerlo solo para un objeto:

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

Como pregunta secundaria: ¿las inserciones que usan la notación ${} protegidas contra las inyecciones de SQL?