預定義異常:
為了 Oracle 開發和維護的方便,在 Oracle 異常中,為常見的異常碼定義了對應的異常名稱,稱為預定義異常,常見的預定義異常有:
異常名稱 | 異常碼 | 描述 |
DUP_VAL_ON_INDEX | ORA-00001 | 試圖向唯一索引列插入重復值 |
INVALID_CURSOR | ORA-01001 | 試圖進行非法游標操作。 |
INVALID_NUMBER | ORA-01722 | 試圖將字符串轉換為數字 |
NO_DATA_FOUND | ORA-01403 | SELECT INTO 語句中沒有返回任何記錄。 |
TOO_MANY_ROWS | ORA-01422 | SELECT INTO 語句中返回多於 1 條記錄。 |
ZERO_DIVIDE | ORA-01476 | 試圖用 0 作為除數。 |
CURSOR_ALREADY_OPEN | ORA-06511 | 試圖打開一個已經打開的游標 |
PL/SQL 中用 EXCEPTION 關鍵字開始異常處理。具體語法是:語法格式:異常處理
BEGIN --可執行部分 EXCEPTION -- 異常處理開始 WHEN 異常名 1 THEN --對應異常處理 WHEN 異常名 2 THEN --對應異常處理 …… WHEN OTHERS THEN --其他異常處理 END; |
語法解析:
異常發生時,進入異常處理部分,具體的異常與若干個 WHEN 子句中指明的異常名匹配,匹配成功就進入對應的異常處理部分,如果對應不成功,則進入 OTHERS 進行處理。
案例:
代碼演示:異常處理 SQL> DECLARE 2 newSal emp.sal % TYPE; 3 BEGIN 4 SELECT sal INTO newSal FROM emp; 5 EXCEPTION 6 WHEN TOO_MANY_ROWS THEN 7 dbms_output.put_line('返回的記錄太多了'); 8 WHEN OTHERS THEN 9 dbms_output.put_line('未知異常'); 10 END; 11 / 返回的記錄太多了PL/SQL procedure successfully completed
自定義異常:
除了預定義異常外,用戶還可以在開發中自定義異常,自定義異常可以讓用戶采用與PL/SQL 引擎處理錯誤相同的方式進行處理,用戶自定義異常的兩個關鍵點:
1. 異常定義:在 PL/SQL 塊的聲明部分采用 EXCEPTION 關鍵字聲明異常,定義方法與定義變量相同。比如聲明一個 myexception 異常方法是:
myexception EXCEPTION;
2. 異常引發:在程序可執行區域,使用 RAISE 關鍵字進行引發。比如引發 myexception方法是:
RAISE myexception;
案例:
代碼演示:自定義異常 SQL> DECLARE 2 sal emp.sal%TYPE; 3 myexp EXCEPTION; ① 4 BEGIN 5 SELECT sal INTO sal FROM emp WHERE ename='JAMES'; 6 IF sal<5000 THEN 7 RAISE myexp; ② 8 END IF; 9 EXCEPTION 10 WHEN NO_DATA_FOUND THEN 11 dbms_output.put_line('NO RECORDSET FIND!'); 12 WHEN MYEXP THEN ③ 13 dbms_output.put_line('SAL IS TO LESS!'); 14 END; 15 / SAL IS TO LESS! PL/SQL procedure successfully completed 代碼解析: ① 用 EXCEPTION 定義一個異常變量 myexp
② 在一定條件下用 RAISE 引發異常 myexp ③ 在異常處理部分,捕獲異常,如果不處理異常,該異常就拋給程序執行者。
引發應用程序異常
在 Oracle 開發中,遇到的系統異常都有對應的異常碼,在應用系統開發中,用戶自定義的異常也可以指定一個異常碼和異常信息, Oracle 系統為用戶預留了自定義異常碼,其范圍介於-20000 到-20999 之間的負整數。引發應用程序異常的語法是:
RAISE_APPLICATION_ERROR(異常碼,異常信息)
案例:
代碼演示:引發應用系統異常 SQL> DECLARE 2 sal emp.sal%TYPE; 3 myexp EXCEPTION; 4 BEGIN 5 SELECT sal INTO sal FROM emp WHERE ename='JAMES'; 6 IF sal<5000 THEN 7 RAISE myexp; 8 END IF; 9 EXCEPTION 10 WHEN NO_DATA_FOUND THEN 11 dbms_output.put_line('NO RECORDSET FIND!'); 12 WHEN MYEXP THEN 13 RAISE_APPLICATION_ERROR(-20001,'SAL IS TO LESS!'); ① 14 END; 15 / ORA-20001: SAL IS TO LESS! ② ORA-06512: 在 line 14 代碼解析: ① 引發應用系統異常,指明異常碼和異常信息。 ② 在控制台上顯示異常碼和異常信息。
如果要處理未命名的內部異常,必須使用 OTHERS 異常處理器。也可以利用 PRAGMA EXCEPTION_INIT 把一個異常碼與異常名綁定。PRAGMA 由編譯器控制, PRAGMA 在編譯時處理,而不是在運行時處理。 EXCEPTION_INIT告訴編譯器將異常名與 ORACLE錯誤碼綁定起來,這樣可以通過異常名引用任意的內部異常,並且可以通過異常名為異常編寫適當的異常處理器。 PRAGMA EXCEPTION_INIT 的語法是:
PRAGMA EXCEPTION_INIT(異常名,異常碼)
這里的異常碼可以是用戶自定義的異常碼,也可以是 Oracle 系統的異常碼。
案例:
代碼演示:PRAGMA EXCEPTION_INIT 異常 <<outterseg>> DECLARE null_salary EXCEPTION; PRAGMA EXCEPTION_INIT(null_salary, -20101); ① BEGIN <<innerStart>> ② DECLARE curr_comm NUMBER; BEGIN SELECT comm INTO curr_comm FROM emp WHERE empno = &empno; IF curr_comm IS NULL THEN RAISE_APPLICATION_ERROR(-20101, 'Salary is missing'); ③ ELSE dbms_output.put_line('有津貼'); END IF; END; EXCEPTION WHEN NO_DATA_FOUND THEN dbms_output.put_line('沒有發現行'); WHEN null_salary THEN dbms_output.put_line('津貼未知'); ④ WHEN OTHERS THEN dbms_output.put_line('未知異常'); END; 代碼解析:
① 把異常名稱 null_salary 與異常碼-20101 關聯,該語句由於是預編譯語句,必須放在聲明部分。也就是說-20101 的異常名稱就是 null_salary。 ② 嵌套 PL/SQL 語句塊 ③ 在內部 PL/SQL 語句塊中引發應用系統異常-20101。 ④ 在外部的 PL/SQL 語句塊中就可以用異常名 null_salary 進行捕獲。