sql >> Base de Datos >  >> RDS >> PostgreSQL

Plaquita de varias filas con pg-promise

Soy el autor de pg-promise.

En versiones anteriores de la biblioteca, esto estaba cubierto por ejemplos simplificados dentro del artículo Performance Boost, que sigue siendo una buena lectura cuando se escriben aplicaciones de bases de datos de alto rendimiento.

El enfoque más nuevo es confiar en el espacio de nombres de los ayudantes, que en última instancia es flexible y está 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 (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);

Ver API:ColumnSet, insertar.

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:

  • una sola fila INSERT
  • multi-fila INSERT
  • una sola fila UPDATE
  • varias filas UPDATE

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

Sí, pero no solo. Si está insertando nombres de esquema/tabla/columna dinámicamente, 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 id de cada nuevo registro al mismo tiempo?

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

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

o incluso mejor, obtenga los id-s y convierta el resultado en una matriz de números enteros, utilizando el mapa de métodos:

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

Para entender por qué usamos + allí, consulte:pg-promise devuelve números enteros como cadenas.

ACTUALIZACIÓN-1

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

ACTUALIZACIÓN-2

Con v8.2.1 y versiones posteriores, puede encapsular la generación de consultas estáticas en una función, de modo 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:
await db.none(query);