Sono l'autore di pg-promise.
Nelle versioni precedenti della libreria questo era coperto da esempi semplificati all'interno dell'articolo Performance Boost, che è ancora una lettura importante quando si scrivono applicazioni di database ad alte prestazioni.
L'approccio più recente è affidarsi allo helpers namespace, che in ultima analisi è flessibile e altamente ottimizzato per le prestazioni.
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;
});
See API: ColumnSet, insert.
Un inserto di questo tipo non richiede nemmeno una transazione, perché se un set di valori non viene inserito, nessuno verrà inserito.
Ed è possibile utilizzare lo stesso approccio per generare uno dei seguenti interrogazioni:
- sola riga
INSERT
- multi-fila
INSERT
- sola riga
UPDATE
- multi-fila
UPDATE
Gli inserimenti utilizzano la notazione $ {} protetta da SQL injection?
Sì, ma non da solo. Se si inseriscono dinamicamente nomi schema/tabella/colonna, è importante utilizzare SQL Names, che in combinazione proteggerà il codice dall'iniezione SQL.
questione connessa: PostgreSQL multi-row updates in Node.js
extra
D: Come ottenere id
di ogni nuovo record allo stesso tempo?
A: Semplicemente aggiungendo RETURNING id
alla tua richiesta, e l'esecuzione con il metodo many:
const query = pgp.helpers.insert(values, cs) + 'RETURNING id';
db.many(query)
.then(data => {
// data = [{id: 1}, {id: 2}, ...]
})
.catch(error => {
// error;
});
o, meglio ancora, ottenere l'ID-s, e convertire il risultato in array di interi, usando il metodo map:
db.map(query, [], a => +a.id)
.then(data => {
// data = [1, 2, ...]
})
.catch(error => {
// error;
});
Per comprendere il motivo per cui abbiamo utilizzato +
lì, vedi: pg-promise returns integers as strings.
UPDATE-1
Per l'inserimento di enorme numero di record, vedere Data Imports.
UPDATE-2
Uso V8.2.1 e successivamente, è possibile avvolgere il statica query generazione in una funzione, in modo che possa essere generato all'interno del metodo query rifiutare quando la generazione di query fallisce:
// 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
});
Grazie per l'assistenza. Io uso solo $ {} per inserire dati, usando comunque il metodo che non è nemmeno necessario. – Bomaz
@Bomaz Ho apportato alcune modifiche, quindi sai che puoi generare aggiornamenti su più righe e altri tipi di query allo stesso modo;) –
Nice miglioramenti. Btw, potresti sapere cosa causa errori ETIMEDOUT? Le ottengo occasionalmente (questo è in un lambda aws che si collega a redshift). La query restituisce questo errore dopo circa 2 minuti e non sono sicuro su come risolverlo ulteriormente. – Bomaz