Oracle PL/SQL 中,异常(Exception)
在 Oracle PL/SQL 中,异常(Exception) 是处理运行时错误的机制,能够将错误逻辑与业务逻辑解耦,保证程序的健壮性和可维护性。以下从 原理 和 案例 两个方面详细解析
一、异常处理的核心原理
1. 异常触发机制
-
自动触发:当 PL/SQL 代码执行过程中遇到错误(如除零、查询无数据、唯一约束冲突等),Oracle 会自动抛出异常。
-
手动触发:开发者可以通过
RAISE
或RAISE_APPLICATION_ERROR
手动触发异常(例如业务规则校验失败)。
2. 异常捕获与传播
-
捕获流程:
-
程序执行到错误点时,立即中断当前操作。
-
跳转到当前块的
EXCEPTION
部分。 -
按顺序匹配
WHEN
子句中的异常类型。 -
若找到匹配的异常处理器,执行对应逻辑;否则将异常传播到外层块。
-
-
传播规则:
-
如果当前块未处理异常,异常会向上一级块传递。
-
若所有外层块均未处理,程序终止并向调用者返回错误。
-
3. 异常分类
类型 | 触发方式 | 示例 |
---|---|---|
预定义异常 | Oracle 内置错误(有固定名称) | NO_DATA_FOUND , TOO_MANY_ROWS |
非预定义异常 | Oracle 错误(有错误代码,需手动绑定名称) | ORA-02291(外键约束错误) |
用户自定义异常 | 开发者显式声明并触发的业务错误 | 库存不足、金额无效等 |
二、异常处理案例解析
预定义异常处理
查询员工工资时处理无数据和多行数据错误
DECLAREv_salary EMPLOYEES_TEM.salary%TYPE;
BEGINSELECT salary INTO v_salaryFROM EMPLOYEES_TEMWHERE employee_id = 999; -- 触发 NO_DATA_FOUNDDBMS_OUTPUT.PUT_LINE('salary:' || v_salary) ;
EXCEPTIONWHEN NO_DATA_FOUND THENDBMS_OUTPUT.PUT_LINE('错误:员工不存在!');WHEN TOO_MANY_ROWS THENDBMS_OUTPUT.PUT_LINE('错误:返回多行数据!');WHEN OTHERS THENDBMS_OUTPUT.PUT_LINE('系统错误: ' || SQLERRM);
END;
触发 返回多行数据
非预定义异常处理
处理外键约束错误(ORA-02291)。
DECLAREe_foreign_key EXCEPTION;PRAGMA EXCEPTION_INIT(e_foreign_key, -2291); -- 绑定错误码
BEGININSERT INTO orders (order_id, customer_id) VALUES (1001, 999); -- 假设 customer_id 不存在EXCEPTIONWHEN e_foreign_key THENDBMS_OUTPUT.PUT_LINE('错误:客户ID不存在!');
END;
用户自定义异常
验证订单金额有效性。
DECLAREe_invalid_amount EXCEPTION;v_order_amount NUMBER := -100;
BEGINIF v_order_amount < 0 THENRAISE e_invalid_amount; -- 手动触发异常END IF;EXCEPTIONWHEN e_invalid_amount THENDBMS_OUTPUT.PUT_LINE('错误:金额不能为负数!');
END;
事务回滚与错误日志
转账操作失败时回滚并记录日志
DECLAREv_from_balance NUMBER := 500;v_to_balance NUMBER := 0;
BEGIN-- 扣款UPDATE accounts SET balance = balance - 1000 WHERE account_id = 1001;-- 存款(假设此处出错)UPDATE accounts SET balance = balance + 1000 WHERE account_id = 1002;COMMIT;EXCEPTIONWHEN OTHERS THENROLLBACK;INSERT INTO error_log (error_code, error_msg, error_time)VALUES (SQLCODE, SQLERRM, SYSDATE);COMMIT;RAISE_APPLICATION_ERROR(-20001, '转账失败:' || SQLERRM);
END;
三、关键注意事项
-
异常处理顺序:
-
先捕获具体异常(如
NO_DATA_FOUND
),最后处理WHEN OTHERS
。 -
避免
WHEN OTHERS THEN NULL
(隐藏错误)。
-
-
事务控制:
-
在
EXCEPTION
块中明确COMMIT
或ROLLBACK
。 -
若异常未被处理,Oracle 会自动回滚未提交的事务。
-
-
错误日志记录:
-
使用
SQLCODE
和SQLERRM
获取错误详情。 -
将错误信息持久化到日志表。
-
-
自定义错误:
-
使用
RAISE_APPLICATION_ERROR
抛出自定义业务错误(错误码范围:-20000 到 -20999)。
-
-
核心价值:异常处理将错误逻辑与业务逻辑分离,提升代码可读性和可维护性。
-
适用场景:数据校验、事务控制、批量操作、外部系统调用等。
-
最佳实践:精准捕获异常、明确事务边界、记录错误日志、避免静默失败。
通过合理设计异常处理逻辑,可以有效提升 Oracle PL/SQL 程序的健壮性和容错能力。