使用SQL Continue Handler时如何获取真实SQLCODE返回码?
DB2存储过程:捕获每个约束操作的SQLCODE问题解决
问题描述
在Linux环境下开发DB2存储过程,需要对5张表执行7个约束的删除/添加操作,要求每个操作执行完成后返回对应的SQLCODE。但最初的实现中,使用Continue Handler后会导致SQLCODE被清零,比如连续执行两次删除操作时,第二次所有操作的返回码都显示为0,和实际执行结果不符。
初始代码(存在问题)
Case p_Action When 'DROP' Then Begin Declare Continue Handler for Not_Found Begin End; Set v_MsgText = 'DROP LOC Check Constraint failed.'; Set v_SqlStmt = 'ALTER TABLE LIBRAT.APNVEND_RECORD_APNV_LOC_DATA DROP CONSTRAINT LIBRAT_APNVEND_RECORD_APNV_LOC_DATA_C1'; Execute Immediate v_SqlStmt; Set v_MsgText = 'DROP LOC Check Constraint rc=' || SQLCODE; Call UTL_FILE.PUT_LINE(v_LogHandle, v_MsgText); ...snip...
问题原因
初始代码中的Continue Handler仅做了空处理(Begin End;),当触发Not_Found等异常时,DB2会重置SQLCODE为0以让程序继续执行,导致后续获取到的SQLCODE并非实际操作的返回码。
解决方法及可行代码
通过声明局部变量存储捕获到的错误码,避免直接依赖被重置的SQLCODE,具体实现如下:
Begin Declare l_RetCode Int; Declare Continue Handler for Is_Duplicate, Missing_Keys, Missing_Rows Begin Set l_RetCode = SQLCODE; End; Set v_MsgText = 'ADD LOC Check Constraint failed.'; Set v_SqlStmt = 'ALTER TABLE LIBRAT.APNVEND_RECORD_APNV_LOC_DATA ADD CONSTRAINT LIBRAT_APNVEND_RECORD_APNV_LOC_DATA_C1 CHECK ( APNV_LOC > 0 )'; Execute Immediate v_SqlStmt; Set v_MsgText = 'ADD LOC Check Constraint rc=' || Coalesce(l_RetCode,0); Call UTL_FILE.PUT_LINE(v_LogHandle, v_MsgText); Set l_RetCode = NULL; ...snip...
关键改进点
- 新增局部变量
l_RetCode,专门用于保存Handler捕获到的SQLCODE - 在
Continue Handler中把触发异常时的SQLCODE赋值给l_RetCode,而非空处理 - 操作执行完成后,用
Coalesce(l_RetCode, 0)获取结果:若有异常则用捕获到的错误码,无异常则返回0 - 每次操作结束后重置
l_RetCode为NULL,确保不会影响下一个操作的结果判断
内容的提问来源于stack exchange,提问作者Dave Clark
相关产品推荐
相关产品推荐

