PostgreSQL使用EXCEPTION子句处理错误时如何仅回滚EXECUTE内变更
你猜测的SAVEPOINT就是正确的实现方案,你遇到的问题根源是EXCEPTION块中直接执行ROLLBACK会回滚当前事务的所有未提交变更,而非仅回滚本次循环内的操作,调整后的代码如下:
WHILE nbStatus1 < nbStatus0 AND StatusExec = 1 LOOP BEGIN -- 创建本次循环执行的专属保存点 SAVEPOINT loop_exec_sp; SELECT Id, query INTO idQuery, Selectquery FROM temp_table_test WHERE Status = 0 LIMIT 1; EXECUTE Selectquery; UPDATE temp_table_test SET Status = 1 WHERE Id = idQuery; nbStatus1 := nbStatus1 + 1; EXCEPTION WHEN others THEN -- 仅回滚到本次循环的保存点,不影响之前已执行的变更 ROLLBACK TO SAVEPOINT loop_exec_sp; UPDATE LOGS_TEST_DETAILS SET ENDDATE = NOW(), ERRORMESSAGE = SQLERRM, ERRORCODE = SQLSTATE WHERE TRAITEMENTID = lastTraitementId AND QUERYID = idQuery; StatusExec := 0; END; COMMIT; END LOOP;
核心逻辑说明
- 每次进入循环块后首先创建保存点,标记本次循环执行的起始状态
- 异常触发时仅回滚到该保存点,只会清除本次循环中
EXECUTE执行、temp_table_test更新等操作产生的变更,之前循环的执行结果完全不受影响 - 异常处理中的日志更新操作在回滚保存点之后执行,会正常写入不会被回滚
- 原有
StatusExec := 0的逻辑已经可以实现触发异常后终止循环的需求,无需额外调整
如果你的业务不需要每次循环执行成功就单独提交,可将COMMIT移动到整个循环结束之后执行,不会影响异常回滚的逻辑。
内容的提问来源于stack exchange,提问作者MattRgx
相关产品推荐
相关产品推荐

