Аз съм авторът на pg-promise.
В по-старите версии на библиотеката това беше обхванато от опростени примери в статията Performance Boost, която все още е добро четиво при писане на високопроизводителни приложения за бази данни.
По-новият подход е да се разчита на пространството от имена на помощниците, което в крайна сметка е гъвкаво и оптимизирано за производителност.
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);
Вижте API:ColumnSet, вмъкване.
Такова вмъкване дори не изисква транзакция, защото ако един набор от стойности не успее да се вмъкне, нито една няма да се вмъкне.
И можете да използвате същия подход, за да генерирате някоя от следните заявки:
- едноредов
INSERT
- многоредов
INSERT
- единредов
UPDATE
- многоредов
UPDATE
Защитени ли са вмъкванията, използващи нотация ${}, срещу sql инжекция?
Да, но не сам. Ако вмъквате имена на схеми/таблици/колони динамично, важно е да използвате SQL имена, които в комбинация ще защитят кода ви от SQL инжектиране.
Свързан въпрос:Многоредови актуализации на PostgreSQL в Node.js
екстри
В:Как да получа id
на всеки нов запис по едно и също време?
А: Просто като добавите RETURNING id
към вашата заявка и изпълнението й с метод много:
const query = pgp.helpers.insert(values, cs) + ' RETURNING id';
const res = await db.many(query);
//=> [{id: 1}, {id: 2}, ...]
или дори по-добре, вземете идентификаторите и преобразувайте резултата в масив от цели числа, като използвате карта на метода:
const res = await db.map(query, undefined, a => +a.id);
//=> [1, 2, ...]
За да разберем защо използвахме +
там вижте:pg-promise връща цели числа като низове.
АКТУАЛИЗИРАНЕ-1
За вмъкване на огромен брой записи вижте Импортиране на данни.
АКТУАЛИЗИРАНЕ-2
Използвайки v8.2.1 и по-нова версия, можете да обвиете статичното генериране на заявка във функция, така че да може да бъде генерирано в метода на заявката, за да отхвърлите, когато генерирането на заявка не успее:
// 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);