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;
});
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?