pragma exception_init绑定错误号必须带负号,如ora-02291须写为-2291;非预定义异常需先声明变量再用pragma绑定,且仅在当前pl/sql单元内有效。

PRAGMA EXCEPTION_INIT 绑定错误号必须带负号
Oracle 错误号在 PRAGMA EXCEPTION_INIT 中必须写成负数,比如外键违例 ORA-02291 要写成 -2291,不能写成 2291 或 02291。否则绑定失败,后续 WHEN 子句永远无法捕获该异常。
常见错误现象:
- 明明写了
PRAGMA EXCEPTION_INIT(fk_err, 2291),但触发外键违例时仍落到WHEN OTHERS - 调试时用
DBMS_OUTPUT.PUT_LINE(SQLCODE)看到输出是-2291,但异常没被自定义名捕获——问题就出在声明时漏了负号
非预定义异常必须先声明变量再绑定
像约束违例(ORA-02290)、外键引用不存在(ORA-02291)、子表存在(ORA-02292)这些都没有内置异常名,得手动走两步:
- 先在
DECLARE部分声明一个异常变量:check_violation EXCEPTION; - 再在同一个作用域内(通常紧接在变量声明后)用
PRAGMA EXCEPTION_INIT(check_violation, -2290);绑定
注意:绑定语句必须出现在过程体的声明区,不能放在 BEGIN 后或 EXCEPTION 块里;也不能跨过程——每个需要捕获该错误的过程都得各自声明+绑定。
WHEN 子句里只能用已绑定的异常名,不能用错误号
EXCEPTION 块中不能写 WHEN -2291 THEN 或 WHEN ORA-02291 THEN,Oracle 不认这种写法。必须使用你通过 PRAGMA 绑定好的变量名:
EXCEPTION
WHEN fk_violation THEN
-- 处理外键错误
WHEN check_violation THEN
-- 处理检查约束错误
WHEN OTHERS THEN
-- 兜底
容易踩的坑:
- 复制粘贴时把异常变量名写错,比如声明的是
fk_err,WHEN里写了fk_violation - 在包规范(PACKAGE SPEC)里声明了异常变量和
PRAGMA,但包体(PACKAGE BODY)里没重新绑定——包体是独立编译单元,绑定不继承
用户自定义错误(-20999 ~ -20000)也要用 PRAGMA 绑定才能精准捕获
用 RAISE_APPLICATION_ERROR(-20001, '订单金额超限') 抛出的错误,默认会被 WHEN OTHERS 捕获。若想单独处理这类业务错误,同样要走声明+绑定流程:
order_amount_exceeded EXCEPTION;PRAGMA EXCEPTION_INIT(order_amount_exceeded, -20001);
这样后续就能写 WHEN order_amount_exceeded THEN ... 做针对性响应,比如返回特定错误码给调用方。不绑定的话,所有 RAISE_APPLICATION_ERROR 都混在 OTHERS 里,日志和分支逻辑都难区分。
真正容易被忽略的是:绑定语句不是“一次配置全局生效”,它只对当前 PL/SQL 单元有效;嵌套过程、包体、匿名块,每个都要自己声明和绑定,少一处就掉进 OTHERS 黑箱。











