1. 首页 > Oracle教程 > 正文

Oracle教程FG075-PL/SQL异常处理

Part02-生产环境规划与建议

2.1 异常处理使用场景

异常处理适用于以下场景:

  • 数据验证:当需要验证用户输入或数据完整性时
  • 数据库操作:当执行数据库操作可能失败时
  • 业务逻辑:当业务逻辑执行可能出现错误时
  • 资源管理:当管理系统资源(如文件、网络连接等)可能失败时
  • 错误恢复:当需要在错误发生后恢复系统状态时

风哥提示:在生产环境中,应为所有可能产生异常的代码添加异常处理。

2.2 异常处理最佳实践

异常处理的最佳实践:

  • 捕获特定异常:尽量捕获特定的异常,而不是使用通用的OTHERS异常
  • 提供有意义的错误信息:在异常处理中提供清晰、有意义的错误信息
  • 记录错误信息:将错误信息记录到日志中,便于调试和排查
  • 适当处理异常:根据异常的类型和严重程度,采取适当的处理措施
  • 保持异常处理简洁:异常处理代码应该简洁明了,避免过于复杂
  • 避免在异常处理中使用COMMIT
    或ROLLBACK
    :这可能会导致事务管理混乱

更多学习教程公众号风哥教程itpux_com

2.3 异常处理性能考虑

使用异常处理时需要考虑的性能因素:

  • 异常捕获的开销:异常捕获会产生一定的性能开销,应避免在频繁执行的代码中使用异常处理
  • 异常处理的复杂度:过于复杂的异常处理会影响程序的执行效率
  • 异常的频率:如果异常发生的频率很高,应考虑优化代码逻辑,而不是依赖异常处理
  • 错误信息的生成:生成详细的错误信息会增加系统开销,应在必要时才生成

from oracle:www.itpux.com

Part03-生产环境项目实施方案

在生产环境中使用PL/SQL异常处理的实施方案:

  1. 需求分析:确定异常处理的需求和场景。
  2. 异常类型定义:定义需要使用的用户定义异常。
  3. 异常处理设计:设计异常处理的逻辑和流程。
  4. 代码实现:实现异常处理代码。
  5. 测试验证:测试异常处理的有效性和性能。
  6. 部署上线:将包含异常处理的代码部署到生产环境。
  7. 监控维护:监控异常的发生情况,及时调整异常处理策略。

Part04-生产案例与实战讲解

4.1 预定义异常处理实战

示例:处理预定义异常

— 创建示例表
CREATE TABLE
fgedu_employees (
emp_id NUMBER PRIMARY KEY,
emp_name VARCHAR2(100),
emp_dept VARCHAR2(50),
emp_salary NUMBER
);
/

— 插入示例数据
INSERT
IN
TO fgedu_employees VALUES (1001, ‘风哥1号’, ‘技术部’, 5000);
INSERT
IN
TO fgedu_employees VALUES (1002, ‘风哥2号’, ‘市场部’, 6000);
COMMIT
;
/

— 处理NO_DATA_FOUND异常
SET SERVEROUTPUT ON;
DECLARE
v_emp_name VARCHAR2(100);
BEGIN
SELECT
emp_name IN
TO v_emp_name
FROM fgedu_employees
WHERE emp_id = 9999;
DBMS_OUTPUT.PUT_LINE(‘员工姓名: ‘ || v_emp_name);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE(‘错误: 未找到指定的员工’);
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(‘错误: ‘ || SQLERRM);
END
;
/

— 处理TOO_MANY_ROWS异常
SET SERVEROUTPUT ON;
DECLARE
v_emp_name VARCHAR2(100);
BEGIN
SELECT
emp_name IN
TO v_emp_name
FROM fgedu_employees;
DBMS_OUTPUT.PUT_LINE(‘员工姓名: ‘ || v_emp_name);
EXCEPTION
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE(‘错误: 查询返回多行数据’);
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(‘错误: ‘ || SQLERRM);
END
;
/

— 处理DUP_VAL_ON_INDEX异常
SET SERVEROUTPUT ON;
DECLARE
BEGIN
INSERT
IN
TO fgedu_employees VALUES (1001, ‘王五’, ‘技术部’, 5500);
COMMIT
;
DBMS_OUTPUT.PUT_LINE(‘员工信息已插入’);
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
DBMS_OUTPUT.PUT_LINE(‘错误: 主键冲突’);
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(‘错误: ‘ || SQLERRM);
END
;
/

错误: 未找到指定的员工

错误: 查询返回多行数据

错误: 主键冲突

更多视频教程www.fgedu.net.cn

4.2 用户定义异常处理实战

示例:处理用户定义异常

— 定义用户异常
SET SERVEROUTPUT ON;
SET SERVEROUTPUT ON;
DECLARE
e_salary_too_low EXCEPTION
;
PRAGMA EXCEPTION_INIT(e_salary_too_low, -20001);
v_emp_id NUMBER :=
1001;
v_new_salary NUMBER :=
1000;
BEGIN
IF
v_new_salary < 2000 THEN RAISE_APPLICATION_ERROR(-20001, '工资不能低于2000');
END IF
;

UPDATE
fgedu_employees
SET emp_salary = v_new_salary
WHERE emp_id = v_emp_id;
COMMIT
;
DBMS_OUTPUT.PUT_LINE(‘工资已更新’);
EXCEPTION
WHEN e_salary_too_low THEN
DBMS_OUTPUT.PUT_LINE(‘错误: ‘ || SQLERRM);
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(‘错误: ‘ || SQLERRM);
END
;
/

— 使用RAISE语句抛出异常
SET SERVEROUTPUT ON;
SET SERVEROUTPUT ON;
DECLARE
e_invalid_dept EXCEPTION
;
v_dept VARCHAR2(50) :=
‘无效部门’;
BEGIN
IF
v_dept NOT IN
(‘技术部’, ‘市场部’, ‘财务部’) THEN
RAISE e_invalid_dept;
END IF
;

DBMS_OUTPUT.PUT_LINE(‘部门有效’);
EXCEPTION
WHEN e_invalid_dept THEN
DBMS_OUTPUT.PUT_LINE(‘错误: 无效的部门’);
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(‘错误: ‘ || SQLERRM);
END
;
/

— 异常处理中的嵌套
SET SERVEROUTPUT ON;
SET SERVEROUTPUT ON;
DECLARE
e_salary_error EXCEPTION
;
v_emp_id NUMBER :=
1001;
v_new_salary NUMBER :=
1500;
BEGIN
BEGIN
IF
v_new_salary < 2000 THEN RAISE e_salary_error;
END IF
;

UPDATE
fgedu_employees
SET emp_salary = v_new_salary
WHERE emp_id = v_emp_id;
COMMIT
;
DBMS_OUTPUT.PUT_LINE(‘工资已更新’);
EXCEPTION
WHEN e_salary_error THEN
DBMS_OUTPUT.PUT_LINE(‘内层异常: 工资过低’);
RAISE;
— 重新抛出异常
END
;
EXCEPTION
WHEN e_salary_error THEN
DBMS_OUTPUT.PUT_LINE(‘外层异常: 工资调整失败’);
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(‘错误: ‘ || SQLERRM);
END
;
/

错误: ORA-20001: 工资不能低于2000

错误: 无效的部门

内层异常: 工资过低
外层异常: 工资调整失败

学习交流加群风哥微信: itpux-com

4.3 异常处理的高级应用

示例:异常处理的高级应用

— 创建错误日志表
CREATE TABLE
fgedu_error_log (
log_id NUMBER PRIMARY KEY,
error_date DATE DEFAULT SYSDATE,
error_message VARCHAR2(4000),
error_code NUMBER,
procedure_name VARCHAR2(100)
);
/

— 创建序列
CREATE SEQUENCE fgedu_error_log_seq START WITH 1 IN
CREMENT BY 1;
/

— 异常处理与日志记录
SET SERVEROUTPUT ON;
DECLARE
v_emp_id NUMBER :=
9999;
v_emp_name VARCHAR2(100);
BEGIN
SELECT
emp_name IN
TO v_emp_name
FROM fgedu_employees
WHERE emp_id = v_emp_id;
DBMS_OUTPUT.PUT_LINE(‘员工姓名: ‘ || v_emp_name);
EXCEPTION
WHEN NO_DATA_FOUND THEN
INSERT
IN
TO fgedu_error_log (log_id, error_message, error_code, procedure_name)
VALUES (fgedu_error_log_seq.NEXTVAL, ‘未找到员工ID: ‘ || v_emp_id, SQLCODE, ‘GET_EMPLOYEE’);
COMMIT
;
DBMS_OUTPUT.PUT_LINE(‘错误已记录到日志’);
WHEN OTHERS THEN
INSERT
IN
TO fgedu_error_log (log_id, error_message, error_code, procedure_name)
VALUES (fgedu_error_log_seq.NEXTVAL, SQLERRM, SQLCODE, ‘GET_EMPLOYEE’);
COMMIT
;
DBMS_OUTPUT.PUT_LINE(‘错误已记录到日志’);
END
;
/

— 验证错误日志
SELECT
*
FROM fgedu_error_log;

— 异常处理与事务管理
SET SERVEROUTPUT ON;
DECLARE
v_emp_id1 NUMBER :=
1001;
v_emp_id2 NUMBER :=
1002;
v_salary_increase NUMBER :=
500;
BEGIN
— 开始事务
UPDATE
fgedu_employees
SET emp_salary = emp_salary + v_salary_increase
WHERE emp_id = v_emp_id1;

— 模拟错误
IF
v_emp_id2 = 1002 THEN
RAISE_APPLICATION_ERROR(-20002, ‘模拟错误’);
END IF
;

UPDATE
fgedu_employees
SET emp_salary = emp_salary + v_salary_increase
WHERE emp_id = v_emp_id2;

— 提交事务
COMMIT
;
DBMS_OUTPUT.PUT_LINE(‘工资调整成功’);
EXCEPTION
WHEN OTHERS THEN
— 回滚事务
ROLLBACK
;
DBMS_OUTPUT.PUT_LINE(‘错误: ‘ || SQLERRM);
DBMS_OUTPUT.PUT_LINE(‘事务已回滚’);
END
;
/

— 验证事务回滚
SELECT
emp_id, emp_name, emp_salary
FROM fgedu_employees
WHERE emp_id IN
(1001, 1002);

错误已记录到日志

LOG_ID ERROR_DATE ERROR_MESSAGE ERROR_CODE PROCEDURE
_NAME
———- ——————- —————————— ———- —————
1 2026-03-31 12:00:00 未找到员工ID: 9999 100 GET_EMPLOYEE

错误: ORA-20002: 模拟错误
事务已回滚

EMP_ID EMP_NAME EMP_SALARY
———- ———- ———-
1001 风哥1号 5000
1002 风哥2号 6000

学习交流加群风哥QQ113257174

Part05-风哥经验总结与分享

风哥提示:在使用PL/SQL异常处理时,应注意以下几点:

  • 全面捕获异常:为所有可能产生异常的代码添加异常处理。
  • 捕获特定异常:尽量捕获特定的异常,而不是使用通用的OTHERS异常。
  • 提供有意义的错误信息:在异常处理中提供清晰、有意义的错误信息。
  • 记录错误信息:将错误信息记录到日志中,便于调试和排查。
  • 适当处理异常:根据异常的类型和严重程度,采取适当的处理措施。
  • 保持异常处理简洁:异常处理代码应该简洁明了,避免过于复杂。
  • 注意事务管理:在异常处理中正确管理事务,避免数据不一致。
  • 测试异常处理:在生产环境中使用异常处理前,应进行充分的测试。

更多学习教程公众号风哥教程itpux_com

from oracle:www.itpux.com

风哥提示:请根据实际情况调整配置和参数,确保生产环境的安全性和稳定性。学习交流加群风哥QQ113257174

生产环境建议:请根据实际情况调整配置和参数,确保生产环境的安全性和稳定性。

风哥提示:更多学习教程公众号风哥教程itpux_com

本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html

联系我们

在线咨询:点击这里给我发消息

微信号:itpux-com

工作日:9:30-18:30,节假日休息