PostgreSQL函数中禁止使用COMMIT/ROLLBACK,因其必须原子执行且嵌入调用者事务;仅PROCEDURE支持事务控制,每次COMMIT/ROLLBACK会结束当前事务并自动开启新事务,嵌套调用共享同一事务上下文。

在 PostgreSQL 的 plpgsql 存储过程里,COMMIT 和 ROLLBACK 是允许使用的,但仅限于 PROCEDURE(过程),不能用于 FUNCTION(函数)。 这是关键前提,踩错类型直接报错。
为什么 FUNCTION 里用 COMMIT 会报错?
PostgreSQL 要求函数必须是“原子性”的:它必须运行在一个由调用者控制的事务上下文中,不能自行结束或重启事务。一旦你在 FUNCTION 里写 COMMIT,就会触发 ERROR: invalid transaction termination。
-
FUNCTION的设计定位是“计算/返回值”,不是“控制事务生命周期” - 即使函数被
CALL(而非SELECT)调用,只要定义为FUNCTION,仍受此限制 - 想用事务控制,必须显式定义为
PROCEDURE,并用CALL执行
PROCEDURE 中 COMMIT/ROLLBACK 的实际行为
每次执行 COMMIT 或 ROLLBACK,不仅结束当前事务,还会自动开启一个新事务(即隐式 BEGIN)。这意味着:
- 后续语句仍在事务中,直到下一个
COMMIT/ROLLBACK或连接断开 -
COMMIT AND CHAIN和ROLLBACK AND CHAIN会保留前一个事务的隔离级别、只读属性等特征,避免手动重复设置 - 游标默认被关闭;但
FOR循环中的COMMIT会让游标转为HOLD状态,保持打开直到循环结束
嵌套 PROCEDURE 调用时的事务归属
所有嵌套调用的 PROCEDURE 共享同一个事务上下文 —— 没有“子事务”概念。所以:
- 内层
PROCEDURE执行COMMIT,整个事务立即提交,外层后续的ROLLBACK失效 - 内层执行
ROLLBACK,整个事务回滚,外层后续的COMMIT也无效 - 这种行为和 Oracle 的自治事务(
AUTONOMOUS_TRANSACTION)完全不同,PostgreSQL 原生不支持自治事务
容易被忽略的关键点
事务控制语句只对 DML(INSERT/UPDATE/DELETE)生效;DDL(如 CREATE TABLE)在 PostgreSQL 中默认自动提交,无法被 ROLLBACK 撤销。另外,COMMIT 后的错误不会导致已提交数据回滚 —— 它只影响该事务中尚未提交的部分。这点在编写含多步逻辑的存储过程时,必须逐段评估失败点与数据一致性边界。










