PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Mehrreihige Einlage mit pg-Versprechen

Ich bin der Autor von pg-promise.

In älteren Versionen der Bibliothek wurde dies durch vereinfachte Beispiele im Artikel zur Leistungssteigerung behandelt, der immer noch eine gute Lektüre beim Schreiben von Hochleistungs-Datenbankanwendungen ist.

Der neuere Ansatz besteht darin, sich auf den helpers-Namespace zu verlassen, der letztendlich flexibel und auf Leistung optimiert ist.

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

Siehe API:ColumnSet, einfügen.

Eine solche Einfügung erfordert nicht einmal eine Transaktion, denn wenn ein Wertesatz nicht eingefügt werden kann, wird keiner eingefügt.

Und Sie können den gleichen Ansatz verwenden, um eine der folgenden Abfragen zu generieren:

  • einzeilige INSERT
  • Mehrzeiliger INSERT
  • einzeiliges UPDATE
  • mehrzeiliges UPDATE

Sind Einfügungen in der ${}-Notation gegen SQL-Injection geschützt?

Ja, aber nicht allein. Wenn Sie Schema-/Tabellen-/Spaltennamen dynamisch einfügen, ist es wichtig, SQL-Namen zu verwenden, die in Kombination Ihren Code vor SQL-Injection schützen.

Verwandte Frage:Mehrzeilige PostgreSQL-Updates in Node.js

Extras

F:So erhalten Sie id jedes neuen Datensatzes gleichzeitig?

A: Einfach durch Anhängen von RETURNING id zu Ihrer Abfrage hinzufügen und mit method many ausführen:

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

oder noch besser, holen Sie sich die id-s und konvertieren Sie das Ergebnis mit der Methode map:

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

Um zu verstehen, warum wir + verwendet haben siehe dort:pg-promise gibt ganze Zahlen als Strings zurück.

UPDATE-1

Informationen zum Einfügen einer großen Anzahl von Datensätzen finden Sie unter Datenimporte.

UPDATE-2

Mit v8.2.1 und höher können Sie die statische Abfragegenerierung in eine Funktion packen, sodass sie innerhalb der Abfragemethode generiert werden kann, um abzulehnen, wenn die Abfragegenerierung fehlschlägt:

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