如何一次插入两张表?
我需要插入第user_information
字段user_id
,第一个表user
插入返回id
,我找到this answer但我找不到如何成为用params编写的陈述
var dbQuery = 'WITH insertUser AS (
INSERT INTO "user" (status, create_date) VALUES ($1, $2) RETURNING id
)
, insertUserInformation AS (
INSERT INTO user_information (user_id, email) VALUES ($3, $4)
)
';
yield queryPromise(dbClient, dbQuery, [status, timestamp, ??, email]);
答案 0 :(得分:1)
在postgresql中不可能。我通过创建函数并简单地使用参数执行来解决完全相同的问题。正如我在你的表结构中看到的那样,你没有很多属性,所以这将相对容易。
示例代码:
function.sql
CREATE OR REPLACE FUNCTION createSomething
(
IN attr1 VARCHAR(20),
IN attr2 VARCHAR(200)
)
RETURNS void AS $$
DECLARE userId INTEGER;
BEGIN
INSERT INTO table1 (col1, col2) VALUES
(
attr1,
attr2
) RETURNING id INTO userId;
INSERT INTO table2 (user_id, col11, col2) VALUES
(
userId,
col11,
col12
);
END;
$$ LANGUAGE plpgsql;
用法:
SELECT createSomething('value1', 'value2');
请注意,第二个插入语句将知道最近用户的ID是什么,并将使用它。
答案 1 :(得分:1)
使用交易。这样,将提交所有查询,或者不提交任何查询。并且在执行所有查询之前的不完整状态对于其他进程是不可见的。
https://github.com/brianc/node-postgres/wiki/Transactions
提供了有关如何在node-postgres
进行交易的详情
作为参考,最相关的部分是:
var Client = require('pg').Client;
var client = new Client(/*your connection info goes here*/);
client.connect();
var rollback = function(client) {
//terminating a client connection will
//automatically rollback any uncommitted transactions
//so while it's not technically mandatory to call
//ROLLBACK it is cleaner and more correct
client.query('ROLLBACK', function() {
client.end();
});
};
client.query('BEGIN', function(err, result) {
if(err) return rollback(client);
client.query('INSERT INTO account(money) VALUES(100) WHERE id = $1', [1], function(err, result) {
if(err) return rollback(client);
client.query('INSERT INTO account(money) VALUES(-100) WHERE id = $1', [2], function(err, result) {
if(err) return rollback(client);
//disconnect after successful commit
client.query('COMMIT', client.end.bind(client));
});
});
});
答案 2 :(得分:0)
PostgreSQL准备好的声明不允许你这样做。您必须使用交易。
以下是使用ES6生成器使用pg-promise实现的示例,因为这似乎是您问题的偏好。
var pgp = require('pg-promise')({
// initialization options;
});
var db = pgp(/* your connection object or string */);
db.tx(function*(t) {
let user = yield t.one('INSERT INTO user(status, create_date) VALUES($1, $2) RETURNING id', [status, timestamp]);
yield t.none('INSERT INTO user_information(user_id, email) VALUES($1, $2)', [user.id, email]);
})
.then(()=> {
// SUCCESS;
})
.catch(error=> {
// ERROR;
});
或者您可以对yield
的结果使用db.tx
,因为它会返回一个承诺。
答案 3 :(得分:-1)
我不相信这可以作为一个自然的sql语句来完成。你必须把它作为一个程序或其他机制包装起来。