PL/SQL匿名块未触发自定义异常:信用卡位数不足约束违规咨询
为什么你的Oracle匿名块没触发自定义异常?
嘿,这事儿我太熟了!核心问题出在数据库约束的优先级比你的PL/SQL自定义逻辑高太多——简单说,数据库会在你的代码判断之前就把违规操作拦下来了。
背后的逻辑是这样的:
- 你建表时加的信用卡号长度约束(比如CHECK或者VARCHAR2长度限制)是数据库底层的校验规则,当你执行UPDATE语句的时候,数据库会先检查这条SQL是否违反约束,一旦发现位数不够,立刻抛出系统自带的约束违规异常(比如
ORA-02290或者ORA-01401),这时候你的匿名块还没走到自定义异常的判断逻辑呢! - 你的自定义异常是在PL/SQL代码里定义的,但数据库的约束校验是SQL执行的第一环节,根本轮不到你的代码去触发自定义异常。
给你两个解决办法:
办法一:自己接管校验逻辑,去掉数据库约束
如果想完全用自定义异常处理,直接把表上的长度约束删掉,在匿名块里先校验卡号长度,符合要求再执行更新:
DECLARE e_short_ccn EXCEPTION; -- 定义自定义异常 v_target_ccn VARCHAR2(20) := '1234'; -- 要更新的短卡号 BEGIN -- 先做长度校验 IF LENGTH(v_target_ccn) < 16 THEN RAISE e_short_ccn; -- 触发自定义异常 END IF; -- 校验通过再执行更新 UPDATE credit_cards SET card_number = v_target_ccn WHERE id = 1; COMMIT; EXCEPTION WHEN e_short_ccn THEN DBMS_OUTPUT.PUT_LINE('自定义异常提示:信用卡号码位数过少,请输入至少16位!'); ROLLBACK; WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('系统异常:' || SQLERRM); ROLLBACK; END; /
办法二:保留数据库约束,把系统异常映射成自定义处理
要是不想删约束,那就把系统的约束违规异常和你的自定义异常绑定,在异常块里做自定义提示:
DECLARE e_short_ccn EXCEPTION; -- 把系统错误码和自定义异常绑定(这里假设是CHECK约束违规,码是-02290,你要根据自己的约束查对应码) PRAGMA EXCEPTION_INIT(e_short_ccn, -02290); BEGIN UPDATE credit_cards SET card_number = '1234' WHERE id = 1; COMMIT; EXCEPTION WHEN e_short_ccn THEN DBMS_OUTPUT.PUT_LINE('自定义提示:信用卡号码位数不够,不符合要求!'); ROLLBACK; WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('其他异常:' || SQLERRM); ROLLBACK; END; /
注意:不同约束的错误码不一样,比如VARCHAR2长度超限是ORA-01401,CHECK约束违规是ORA-02290,你可以查一下实际抛出的错误码来替换。
总结一下
不是你的自定义异常写得不对,是数据库的约束校验抢在了前面,根本没给你的代码触发自定义异常的机会。选上面两个办法里的任意一个,就能实现你想要的自定义异常/提示效果啦!
内容的提问来源于stack exchange,提问作者Giles Bonner
相关产品推荐
相关产品推荐

