在通过 CALL 命令调用的过程中以及在匿名代码块 (DO 命令) 中,可以使用 COMMIT 和 ROLLBACK 命令结束事务。使用这些命令结束事务后,会自动启动一个新事务,因此没有单独的 START TRANSACTION 命令。(请注意,BEGIN 和 END 在 PL/pgSQL 中有不同的含义。)
这是一个简单的示例
CREATE PROCEDURE transaction_test1()
LANGUAGE plpgsql
AS $$
BEGIN
FOR i IN 0..9 LOOP
INSERT INTO test1 (a) VALUES (i);
IF i % 2 = 0 THEN
COMMIT;
ELSE
ROLLBACK;
END IF;
END LOOP;
END;
$$;
CALL transaction_test1();
新事务以默认事务特性(例如事务隔离级别)开始。在循环中提交事务时,可能需要自动以与前一个事务相同的特性启动新事务。命令 COMMIT AND CHAIN 和 ROLLBACK AND CHAIN 可以实现此目的。
事务控制仅在从顶级或嵌套 CALL 或 DO 调用(没有任何其他介入命令)中进行 CALL 或 DO 调用时才可能。例如,如果调用堆栈为 CALL proc1() → CALL proc2() → CALL proc3(),则第二个和第三个过程可以执行事务控制操作。但是,如果调用堆栈为 CALL proc1() → SELECT func2() → CALL proc3(),则最后一个过程无法进行事务控制,因为中间有 SELECT。
游标循环有特殊注意事项。请考虑以下示例
CREATE PROCEDURE transaction_test2()
LANGUAGE plpgsql
AS $$
DECLARE
r RECORD;
BEGIN
FOR r IN SELECT * FROM test2 ORDER BY x LOOP
INSERT INTO test1 (a) VALUES (r.x);
COMMIT;
END LOOP;
END;
$$;
CALL transaction_test2();
通常,游标会在事务提交时自动关闭。但是,像这样作为循环一部分创建的游标会在第一次 COMMIT 或 ROLLBACK 时自动转换为可保持游标。这意味着游标会在第一次 COMMIT 或 ROLLBACK 时完全求值,而不是逐行求值。游标在循环后仍会自动删除,因此用户几乎看不到它。
在由非只读命令(例如 UPDATE ... RETURNING)驱动的游标循环中不允许使用事务命令。
事务无法在具有异常处理程序的块内结束。
如果您在文档中看到任何不正确、与您对特定功能的体验不符或需要进一步澄清的内容,请使用此表单报告文档问题。