Многострочные обновления PostgreSQL в Node.js
Как я уже нашел здесь, в Stackru можно обновить несколько строк в одном запросе, выполнив что-то вроде этого
update test as t set
column_a = c.column_a,
column_c = c.column_c
from (values
('123', 1, '---'),
('345', 2, '+++')
) as c(column_b, column_a, column_c)
where c.column_b = t.column_b;
отдельное спасибо @Roman Pekar за четкий ответ.
Теперь я пытаюсь объединить этот способ обновления с запросом к базе данных postgreSQL в NodeJS.
Вот фрагмент моего кода:
var requestData = [
{id: 1, value: 1234}
{id: 2, value: 5678}
{id: 3, value: 91011}
]
client.connect(function (err) {
if (err) throw err;
client.query(buildStatement(requestData), function (err, result) {
if (err) throw err;
res.json(result.rows);
client.end(function (err) {
if (err) throw err;
});
});
});
var buildStatement = function(requestData) {
var params = [];
var chunks = [];
for(var i = 0; i < requestData.length; i++) {
var row = requestData[i];
var valuesClause = [];
params.push(row.id);
valuesClause.push('$' + params.length);
params.push(row.value);
valuesClause.push('$' + params.length);
chunks.push('(' + valuesClause.join(', ') + ')');
}
return {
text: 'UPDATE fit_ratios as f set ratio_budget = c.ratio_budget from (VALUES ' + chunks.join(', ') + ') as c(ratio_label, ratio_budget) WHERE c.ratio_label = f.ratio_label', values: params
}
}
я не получаю ошибку, но она не обновляет мою таблицу, я действительно не знаю, что здесь не так. Возможно, синтаксическая ошибка в моем коде запроса? Я просто не нахожу конкретных примеров многострочных запросов при обновлении в пакете NodeJS pg
2 ответа
Приведенный ниже пример основан на библиотеке pg- promis и ее методе helpers.update:
// library initialization, usually placed in its own module:
const pgp = require('pg-promise')({
capSQL: true // capitalize all generated SQL
});
const db = pgp(/*your connection details*/);
// records to be updated:
const updateData = [
{id: 1, value: 1234},
{id: 2, value: 5678},
{id: 3, value: 91011}
];
// declare your ColumnSet once, and then reuse it:
const cs = new pgp.helpers.ColumnSet(['?id', 'value'], {table: 'fit_ratios'});
// generating the update query where it is needed:
const update = pgp.helpers.update(updateData, cs) + ' WHERE v.id = t.id';
//=> UPDATE "fit_ratios" AS t SET "value"=v."value"
// FROM (VALUES(1,1234),(2,5678),(3,91011))
// AS v("id","value") WHERE v.id = t.id
// executing the query:
db.none(update)
.then(()=> {
// success;
})
.catch(error=> {
// error;
});
Этот метод создания многострочных обновлений можно охарактеризовать как:
- очень быстро, так как он опирается на тип ColumnSet, который реализует интеллектуальное кэширование для генерации запросов
- полностью безопасен, поскольку все типы данных проходят через механизм форматирования запросов библиотеки, чтобы убедиться, что все отформатировано и экранировано правильно.
- очень гибкий, благодаря расширенному синтаксису ColumnConfig, поддерживаемому для определения столбцов.
- очень прост в использовании, благодаря упрощенному интерфейсу, реализованному pg-обещанием.
Обратите внимание, что мы используем ?
перед колонной id
чтобы указать, что столбец является частью условия, но не подлежит обновлению. Для полного синтаксиса столбца см. Класс Column и структуру ColumnConfig.
Смежный вопрос: многорядная вставка с pg-обещанием.
Прежде всего, я принял ответ от @vitaly-t, поскольку он научил меня использовать более быструю и быструю библиотеку pg-обещания, и это действительно решило мою проблему. (Период)
Но чтобы ответить на мой собственный вопрос для людей, которые могут столкнуться с той же проблемой и хотят остаться с библиотекой pg, вот где я допустил ошибку (это просто синтаксис)
В моем исходном коде у меня была эта строка в конце
return {
text: 'UPDATE fit_ratios as f set ratio_budget = c.ratio_budget from (VALUES ' + chunks.join(', ') + ') as c(ratio_label, ratio_budget) WHERE c.ratio_label = f.ratio_label', values: params
}
}
В первый раз, когда я увидел это, мне было трудно это понять, поэтому было очень легко допустить некоторые ошибки. изменив эту строку кода на то, что вы видите ниже, исправил мою первоначальную проблему
return {
text: 'UPDATE fit_ratios as f set ratio_budget = c.value from (VALUES ' + chunks.join(', ') + ') as c(id, value) WHERE c.id = f.ratio_id',
values: params
}
Я просто пропустил использование имен столбцов вместо ключей моего объекта. (egcratio_label to c.id,...)