12

我正在使用三个插入语句,如果第三个语句有错误,我想回滚第一个和第二个。如果没有办法做到这一点,请告诉我在 PostgresqQL 中处理此问题的不同方法。

如果我使用COMMITor ROLLBACK,我会得到一个错误。

CREATE OR REPLACE FUNCTION TEST1 ()
   RETURNS VOID
   LANGUAGE 'plpgsql'
   AS $$
BEGIN 

    INSERT INTO table1 VALUES (1);

    INSERT INTO table1 VALUES (2);

    INSERT INTO table1 VALUES ('A');
    COMMIT;
EXCEPTION
   WHEN OTHERS THEN
   ROLLBACK;
END;$$;

上面的代码不起作用;COMMIT并且ROLLBACK不受 PostgreSQL 函数支持。

4

2 回答 2

27

您不能在函数中 SAVEPOINT使用类似COMMIT或的事务语句。文档说:ROLLBACK

CALL命令调用的过程以及匿名代码块 ( DOcommand) 中,可以使用命令COMMITROLLBACK.

Ex negativo,因为函数不是用 调用的过程,所以CALL你不能在函数中这样做。

BEGINPL/pgSQL 中启动块的语句BEGIN与启动事务的 SQL 语句不同。

只需COMMIT从您的函数中删除,您就有了解决方案:由于整个函数始终在单个事务中运行,因此第三条语句中的任何错误都将导致 aROLLBACK也撤消前两条语句。

于 2018-01-16T09:16:26.750 回答
4

与其他 SQL 语言相比,您应该认为 Postgres 总是在事务中隐式处理提交/回滚以防出错。

这是文档所说的:

事务是所有数据库系统的基本概念。事务的要点在于它将多个步骤捆绑到一个单一的、全有或全无的操作中。步骤之间的中间状态对其他并发事务是不可见的,并且如果发生阻止事务完成的某些故障,则这些步骤根本不会影响数据库。

CREATE OR REPLACE FUNCTION TEST1 ()
   RETURNS VOID
   LANGUAGE 'plpgsql'
   AS $$
BEGIN 

    INSERT INTO table1 VALUES (1);

    INSERT INTO table1 VALUES (2);

    INSERT INTO table1 VALUES ('A');
    COMMIT;
EXCEPTION
   WHEN OTHERS THEN
   ROLLBACK;
END;$$;
于 2020-01-23T17:27:26.007 回答