jri*_*iro 5 postgresql upsert node.js pg
我正在尝试使用带有 pg 扩展名(版本 0.5.4)的 node.js 在 postgres 数据库中进行插入或更新。
到目前为止,我有这个代码:(...)
client.query({
text: "update users set is_active = 0, ip = $1 where id=$2",
values: [ip,id]
}, function(u_err, u_result){
debug(socket_id,"update query result: ",u_result);
debug(socket_id,"update query error: ",u_err);
date_now = new Date();
var month = date_now.getMonth() + 1;
if(!u_err){
client.query({
text: 'insert into users (id,first_name,last_name,is_active,ip,date_joined) values' +
'($1,$2,$3,$4,$5,$6)',
values: [
result.id,
result.first_name,
result.last_name,
1,
ip,
date_now.getFullYear() + "-" + month + "-" + date_now.getDate() + " " + date_now.getHours() + ":" + date_now.getMinutes() + ":" + date_now.getSeconds()
]
}, function(i_err, i_result){
debug(socket_id,"insert query result: ",i_result);
debug(socket_id,"insert query error: ",i_err);
});
}
});
Run Code Online (Sandbox Code Playgroud)
问题是,虽然两个查询都有效,但问题总是同时运行,而不是仅在更新失败时运行插入函数。
代码输出中的调试功能类似于:
更新
Object { type="update query result: ", debug_value={...}}
home (linha 56)
Object { type="update query error: ", debug_value=null}
home (linha 56)
Object { type="insert query result: "}
home (linha 56)
Object { type="insert query error: ", debug_value={...}}
Run Code Online (Sandbox Code Playgroud)
插入
Object { type="update query result: ", debug_value={...}}
home (linha 56)
Object { type="update query error: ", debug_value=null}
home (linha 56)
Object { type="insert query result: ", debug_value={...}}
home (linha 56)
Object { type="insert query error: ", debug_value=null}
Run Code Online (Sandbox Code Playgroud)
** 编辑 **
来自 node-postgres 开发人员的回答:
可以检索受插入和更新影响的行数。它没有在本机绑定中完全实现,但在纯 javascript 版本中确实有效。我将在接下来的一两周内解决这个问题。同时使用纯 javascript 版本并在这里查看:
https://github.com/brianc/node-postgres/blob/master/test/integration/client/result-metadata-tests.js
** 结束编辑 **
任何人都可以帮忙吗?
您问题的直接答案是使用存储过程进行更新插入。
http://www.postgresql.org/docs/current/static/plpgsql-control-structs.html#PLPGSQL-UPSERT-EXAMPLE
像这样的东西与 pg 模块一起工作得很好。
client.query({
text: "SELECT upsert($1, $2, $3, $4, $5, $6)"
values: [ obj.id,
obj.first_name,
obj.last_name,
1,
ip,
date_now.getFullYear() + "-" + month + "-" + date_now.getDate() + " " + date_now.getHours() + ":" + date_now.getMinutes() + ":" + date_now.getSeconds()
]
}, function(u_err, u_result){
if(err) // this is a real error, handle it
// otherwise your data is updated or inserted properly
});
Run Code Online (Sandbox Code Playgroud)
当然,这假设您正在使用某种具有您需要的所有值的模型对象,即使它们没有改变。您必须将它们全部传递到 upsert 中。如果您坚持按照此处所示的方式进行操作,您可能应该在更新后检查实际的错误对象,以确定它是否因该行已经存在而失败,或者由于某些其他原因(这是真正的数据库错误)需要处理)。
然后,您必须处理更新失败的时间和插入完成的时间之间潜在的竞争条件。如果其他函数尝试使用相同的 id 进行插入,则会出现问题。交易对此有好处。这就是我现在所得到的。希望能帮助到你。