PL/SQL中自定义异常必须先DECLARE再RAISE,作用域限本块;RAISE_APPLICATION_ERROR用于返回标准错误码和消息,触发即终止并需显式事务控制。

必须先声明再 RAISE,不能像 PostgreSQL 那样直接 RAISE EXCEPTION;否则会报 ERROR: unrecognized exception。
DECLARE 区必须显式声明异常变量
PL/SQL 不允许在未声明的情况下使用自定义异常名。你不能写 RAISE e_invalid_input,除非 e_invalid_input 已在 DECLARE 部分定义为 EXCEPTION 类型。
- 声明语法固定:
e_my_error EXCEPTION; - 异常变量作用域仅限当前 PL/SQL 块(含子块),不可跨过程引用
- 不能赋值、不能出现在 SQL 语句中,只用于
RAISE和WHEN分支 - 若需全局复用,应放在包规范(
PACKAGE)中声明,调用时加包前缀,如my_pkg.e_timeout
RAISE 后必须在 EXCEPTION 块中显式捕获
自定义异常不会自动传播到外层块——除非你手动 RAISE 且外层有对应 WHEN 分支。未被捕获的自定义异常会导致整个事务回滚并抛出 ORA-06510: PL/SQL: unhandled user-defined exception。
- 触发方式只有
RAISE e_my_error;,不能带消息或代码 - 若想附带可读信息,必须搭配
DBMS_OUTPUT.PUT_LINE或日志表写入,RAISE本身不携带文本 - 不要依赖
WHEN OTHERS THEN捕获自定义异常——它能捕获,但会丢失异常身份,无法做差异化处理 - 多个自定义异常建议按业务语义分组命名,如
e_insufficient_balance、e_expired_token,便于后续维护
需要错误码和消息?用 RAISE_APPLICATION_ERROR
当你要向调用方返回明确的错误编号(-20000 ~ -20999)和可读消息时,RAISE_APPLICATION_ERROR 是唯一合规方式。它绕过异常变量声明,直接终止执行并抛出带上下文的错误。
- 语法:
RAISE_APPLICATION_ERROR(-20001, '余额不足'); - 该语句会立即退出当前块,不执行后续逻辑,也不受当前
EXCEPTION块保护(除非外层捕获) - 调用方(如 JDBC 或 SQL*Plus)收到的是标准
ORA-20001错误,SQLCODE返回 -20001,SQLERRM返回完整消息 - 注意:它不能被
WHEN e_my_error THEN捕获,只能被WHEN OTHERS THEN或对应SQLCODE的非预定义异常机制捕获(需配合PRAGMA EXCEPTION_INIT)
真正容易被忽略的是事务边界:无论用哪种方式抛出自定义异常,只要没在异常处理分支里显式 COMMIT 或 ROLLBACK,Oracle 默认保持事务打开状态——而大多数业务逻辑要求失败即回滚。所以,每个 WHEN 分支末尾,该 ROLLBACK 就得 ROLLBACK,别指望上层兜底。

















