Postgresql捕获事务错误和回滚

时间:2016-07-25 00:38:24

标签: node.js postgresql pg-promise

我正在使用 pg-promise 来运行我的SQL查询。查询本身存储在外部.sql文件中。

当我执行一个事务时,如果发生错误(如预期的那样),Postgres将中止该事务。我遇到的问题是我在事务中止后尝试运行的任何单独查询都没有运行,而是我收到此消息: “当前事务中止,命令被忽略,直到事务块结束”。如果查询是在psql控制台中运行的,我可以通过在查询失败后发出ROLLBACK来解决此问题。我不认为这是一个选项,因为我的应用程序使用的SQL位于外部文件中。我也不认为Savepoints是一个选项,因为如果出现问题,应该抛出整个事务。

如果发生此错误,我将如何在SQL文件中回滚?

这是SQL的参考:

BEGIN;

DELETE 
FROM tournament_tossup_values
WHERE tournament_id = $1 AND
NOT EXISTS
(
    SELECT id
    FROM tournament_match
    WHERE tournament_id = $1
);

UPDATE tournament
SET bonus_point_value = $5, parts_per_bonus = $6
WHERE id = $1 AND NOT EXISTS (
    SELECT id 
    FROM tournament_match
    WHERE tournament_id = $1
)
RETURNING bonus_point_value, parts_per_bonus; <-- Any subsequent accesses to the database by the application fail if this transaction fails

COMMIT;  <-- I want to rollback everything if this fails

提前谢谢!

1 个答案:

答案 0 :(得分:1)

在外部SQL文件中实现事务时,您需要为COMMITROLLBACK提供所有正确的处理。如果不这样做,事务状态可能会在服务器端代码中变得不可预测,并导致您获得的错误类型。

这可能有点棘手,说起来容易做起来难。这就是为什么最好的解决方案根本不应该这样做。

您正在使用的模块pg-promise通过方法tx提供可靠的交易处理,这是您应该使用的。

为此,将SQL文件拆分为两个文件 - 一个使用DELETE操作,一个使用UPDATE操作,然后在事务中将它们作为两个查询执行:

db.tx(t => {
    return t.batch([
        t.none('DELETE...'),
        t.any('UPDATE...')
    ]);
})
    .then(data => {
        // success;
    })
    .catch(error => {
        // error;
    });