在由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
命令。
PL/pgSQL不支持保存点(SAVEPOINT
/ROLLBACK TO SAVEPOINT
/RELEASE SAVEPOINT
命令)。保存点的典型使用模式可以用带有异常处理程序的块替换(参见第41.6.8节)。在底层,带有异常处理程序的块形成一个子事务,这意味着无法在这样的块内结束事务。
游标循环需要特殊考虑。请考虑以下示例
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
时完全评估,而不是逐行评估。游标在循环结束后仍会自动删除,因此用户大多不会注意到这一点。但必须记住,游标查询获取的任何表或行锁在第一个COMMIT
或ROLLBACK
之后将不再保留。
在由非只读命令驱动的游标循环中不允许使用事务命令(例如UPDATE ... RETURNING
)。
如果您在文档中看到任何不正确的内容、与您对特定功能的体验不符的内容或需要进一步澄清的内容,请使用此表单报告文档问题。