Node.js 中的 PostgreSQL 多行更新

Posted

技术标签:

【中文标题】Node.js 中的 PostgreSQL 多行更新【英文标题】:PostgreSQL multi-row updates in Node.js 【发布时间】:2016-12-31 09:20:10 【问题描述】:

正如我已经在这里找到的 On ***,可以通过执行类似这样的操作来更新一个查询中的多行

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 的明确回答。

现在我正在尝试将这种更新方式与查询 NodeJS 中的 postgreSQL 数据库合并。

这是我的代码片段:

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 包中更新时,我只是没有找到任何多行查询的具体示例

【问题讨论】:

【参考方案1】:

以下示例基于库pg-promise,及其方法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:
await db.none(update);

这种生成多行更新的方法可以表征为:

非常快,因为它依赖于为查询生成实现智能缓存的类型 ColumnSet 完全安全,因为所有数据类型都经过库的查询格式化引擎,以确保所有内容都正确格式化和转义。 非常灵活,因为列定义支持高级ColumnConfig 语法。 非常易于使用,因为pg-promise 实现了简化的界面。

请注意,我们在id 列前面使用? 表示该列是条件的一部分,但不会被更新。有关完整的列语法,请参阅类 Column 和 ColumnConfig 结构。


相关问题:Multi-row insert with pg-promise.

【讨论】:

v.id = t.id 中的 v 和 t 来自哪里? @dbainbridge 来自helpers.update 文档,如果您只需点击提供给您的链接即可。【参考方案2】:

首先,我确实接受了@vitaly-t 的回答,因为他教我使用更好更快的库pg-promise,它确实解决了我的问题。 (句号)

但是为了回答我自己的问题给那些可能会遇到同样问题并希望留在图书馆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

我只是错过了使用列名而不是使用对象的键。 (例如 c.ratio_label 到 c.id,...)

【讨论】:

这不是 SQLi 的倾向吗?

以上是关于Node.js 中的 PostgreSQL 多行更新的主要内容,如果未能解决你的问题,请参考以下文章

如何从 node.js 中的 postgresql 脚本中读取

Node.js、PostgreSQL 中的事务冲突、乐观并发控制和事务重试

PostgreSQL Node.js 服务器中的 SQLite3 each() 函数的等价物?

MongoDB 或 PostGreSQL 使用 Python Django 和 Express 和 Node js 会更好 [关闭]

使用 Node.js 和 Express.js 在 MySQL 中删除给定值数组的多行

使用 Node JS 连接到在线托管的 PostgreSQL