PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Inserto multifilare con pg-promise

Sono l'autore di pg-promise.

Nelle versioni precedenti della libreria questo era trattato da esempi semplificati all'interno dell'articolo Performance Boost, che è ancora una buona lettura quando si scrivono applicazioni di database ad alte prestazioni.

L'approccio più recente consiste nell'affidarsi allo spazio dei nomi degli helper, che è in definitiva flessibile e 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 (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);

Vedi API:ColumnSet, inserisci.

Tale inserimento non richiede nemmeno una transazione, perché se un insieme di valori non viene inserito, nessuno verrà inserito.

E puoi utilizzare lo stesso approccio per generare una qualsiasi delle seguenti query:

  • riga singola INSERT
  • multiriga INSERT
  • UPDATE a riga singola
  • UPDATE multiriga

Gli inserimenti che utilizzano la notazione ${} sono protetti contro l'iniezione di sql?

Sì, ma non da solo. Se stai inserendo i nomi di schema/tabella/colonna in modo dinamico, è importante utilizzare i nomi SQL, che insieme proteggeranno il tuo codice dall'iniezione SQL.

Domanda correlata:aggiornamenti multiriga di PostgreSQL in Node.js

extra

D:Come ottenere id di ogni nuovo record contemporaneamente?

R: Semplicemente aggiungendo RETURNING id alla tua query ed eseguendola con il metodo many:

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

o ancora meglio, ottieni gli id-s e converti il ​​risultato in un array di numeri interi, usando la mappa del metodo:

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

Per capire perché abbiamo usato + lì, vedi:pg-promise restituisce interi come stringhe.

AGGIORNAMENTO-1

Per inserire un numero enorme di record, vedere Importazioni di dati.

AGGIORNAMENTO-2

Utilizzando v8.2.1 e versioni successive, puoi racchiudere la generazione della query statica in una funzione, in modo che possa essere generata all'interno del metodo di query, per rifiutare quando la generazione della query non riesce:

// 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);