1. 预定义(Predefined)异常
ORACLE预定义的异常情况大约有24个。对这种异常情况的处理,无需在程序中定义,由ORACLE自动将其引发。
2. 非预定义(Predefined)异常
即其他标准的ORACLE错误。对这种异常情况的处理,需要用户在程序中定义,然后由ORACLE自动将其引发。
3. 用户定义(User_define)异常
程序执行过程中,出现编程人员认为的非正常情况。对这种异常情况的处理,需要用户在程序中定义,然后显式地在程序中将其引发。
在PL/SQL中有三种方式抛出异常
通过PL/SQL运行时引擎——抛出Oracle异常
使用RAISE语句——抛出用户定义异常
调用RAISE_APPLICATION_ERROR 存储过程——抛出用户定义异常
因为非预定义异常只有编号,没有名称,所以不能直接处理。
1、在PL/SQL 块的定义部分定义异常情况:
<异常情况> EXCEPTION;
2、将其定义好的异常情况,与标准的ORACLE 错误联系起来,使用EXCEPTION_INIT语句:
INSERT INTO departments VALUES(50, 'FINANCE', 'CHICAGO'); DECLARE v_deptno departments.department_id%TYPE := &deptno; deptno_remaining EXCEPTION; --1、定义异常 PRAGMA EXCEPTION_INIT(deptno_remaining, -2292); --2、关联 -- -2292 是违反一致性约束的错误代码 BEGIN DELETE FROM departments WHERE department_id = v_deptno; EXCEPTION WHEN deptno_remaining THEN --3、处理 DBMS_OUTPUT.PUT_LINE('违反数据完整性约束!'); WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM); END;
用户定义的异常错误是通过显式使用 RAISE 语句来触发。
1、在PL/SQL 块的定义部分定义异常情况 ;
2、RAISE <异常情况>;
3、在PL/SQL 块的异常情况处理部分对异常情况做出相应的处理。
DECLARE v_empno employees.employee_id%TYPE :=&empno; no_result EXCEPTION; --1、定义 BEGIN UPDATE employees SET salary = salary+100 WHERE employee_id = v_empno; IF SQL%NOTFOUND THEN RAISE no_result; --2、抛出 END IF; EXCEPTION WHEN no_result THEN --3、处理 DBMS_OUTPUT.PUT_LINE('你的数据更新语句失败了!'); WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM); END;
调用DBMS_STANDARD(ORACLE提供的包)包所定义的RAISE_APPLICATION_ERROR过程,可以 重新定义异常错误消息,将应用程序专有的错误从服务器端转达到客户端应用程序。它为应用程序提供了一种与ORACLE交互的方法。
语法如下:
RAISE_APPLICATION_ERROR(error_number, error_message, [keep_errors] );
There are two uses for RAISE_APPLICATION_ERROR.
The first is to replace generic Oracle exception messages with our own, more meaningful messages.
The second is to create exception conditions of our own, when Oracle would not throw them.
create or replace procedure new_emp ( p_name in emp.ename%type , p_sal in emp.sal%type , p_job in emp.job%type , p_dept in emp.deptno%type , p_mgr in emp.mgr%type , p_hired in emp.hiredate%type := sysdate ) is invalid_manager exception; --1、定义 PRAGMA EXCEPTION_INIT(invalid_manager, -2291); --2、关联 dummy varchar2(1); begin if trunc(p_hired) > trunc(sysdate) then raise_application_error (-20000, 'NEW_EMP::hiredate cannot be in the future'); --3、抛出自定义异常 end if; insert into emp ( ename , sal , job , deptno , mgr , hiredate ) values ( p_name , p_sal , p_job , p_dept , p_mgr , trunc(p_hired) ); exception when dup_val_on_index then raise_application_error (-20001, 'NEW_EMP::employee called '||p_name||' already exists', true); --3、包装Oracle异常 when invalid_manager then raise_application_error (-20002, 'NEW_EMP::'||p_mgr ||' is not a valid manager'); --3、包装自定义异常 end; /
-- 测试RAISE_APPLICATION_ERROR自定义异常 SQL> exec new_emp ('DUGGAN', 2500, 'SALES', 10, 7782, sysdate+1) BEGIN new_emp ('DUGGAN', 2500, 'SALES', 10, 7782, sysdate+1); END; * ERROR at line 1: ORA-20000: NEW_EMP::hiredate cannot be in the future --ORA-20000 ORA-06512: at "APC.NEW_EMP", line 16 ORA-06512: at line 1 -- 测试RAISE_APPLICATION_ERROR包装自定义异常 SQL> exec new_emp ('DUGGAN', 2500, 'SALES', 10, 8888, sysdate) BEGIN new_emp ('DUGGAN', 2500, 'SALES', 10, 8888, sysdate); END; * ERROR at line 1: ORA-20002: NEW_EMP::8888 is not a valid manager ORA-06512: at "APC.NEW_EMP", line 42 ORA-06512: at line 1 -- 测试RAISE_APPLICATION_ERROR包装Oracle异常 SQL> exec new_emp ('DUGGAN', 2500, 'SALES', 10, 7782, sysdate) PL/SQL procedure successfully completed. SQL> SQL> exec new_emp ('DUGGAN', 2500, 'SALES', 10, 7782, sysdate) BEGIN new_emp ('DUGGAN', 2500, 'SALES', 10, 7782, sysdate); END; * ERROR at line 1: ORA-20001: NEW_EMP::employee called DUGGAN already exists ORA-06512: at "APC.NEW_EMP", line 37 ORA-00001: unique constraint (APC.EMP_UK) violated --同时打印原始堆栈 ORA-06512: at line 1