Oracle中的異常能夠分爲哪幾類?程序員
異常(EXCEPTION)處理是用來處理正常執行過程當中未預料到的事件,包括程序塊的異常處理、預約義的錯誤和自定義錯誤。若是PL/SQL程序塊一旦產生異常,而程序並沒有指出如何處理,那麼程序就會自動終止運行。數據庫
異常處理部分通常放在PL/SQL程序體的後半部分,結構以下所示:微信
EXCEPTION網絡
WHEN first_exception THEN <code to handle first exception >app
WHEN second_exception THEN <code to handle second exception >ide
WHEN OTHERS THEN <code to handle OTHERS exception >函數
對於異常處理,須要注意如下幾點內容:學習
(1)異常處理能夠按任意次序排列,但OTHERS必須放在最後。編碼
(2)當程序出現異常時,程序當即暫停工做,跳轉到EXCEPTION部分。使用WHEN … THEN來處理系統定義的異常。使用WHEN OTHERS THEN處理未定義的異常。spa
(3)當異常處理結束後,Oracle就將處理權交給調用者。結束PL/SQL塊的運行。
Oracle將異常分爲預約義異常、非預約義異常和自定義異常三種。
1、預約義異常(Predefined)
當PL/SQL應用程序違反了Oracle規定的限制時,就會隱含地觸發一個內部異常,這就是預約義異常。預約義異常用於處理常見的Oracle錯誤,對這種異常狀況的處理,無需在程序中定義,由Oracle自動將其觸發。它們所有放在PL/SQL自帶的標準包中,這樣程序員就無需再次定義了。預約義異常大約有20多個,下表是一些常見的預約義異常:
表 5-3 Oracle預約義異常
錯誤號 |
異常錯誤信息名稱 |
說明 |
ORA-01403 |
NO_DATA_FOUND |
SELECT INTO沒有找到數據 |
ORA-01422 |
TOO_MANY_ROWS |
SELECT INTO返回多行 |
ORA-06501 |
PROGRAM_ERROR |
內部錯誤,需從新安裝數據字典視圖和PL/SQL包 |
ORA-06511 |
CURSOR_ALREADY_OPEN |
試圖打開一個已存在的遊標 |
ORA-06530 |
ACCESS_INTO_NULL |
試圖爲NULL對象的屬性賦值 |
ORA-01012 |
NOT_LOGGED_ON |
沒有鏈接到Oracle |
ORA-01001 |
INVALID_CURSOR |
試圖使用一個無效的遊標 |
ORA-00061 |
TRANSACTION_BACKED_OUT |
因爲發生死鎖事務被撤消 |
ORA-00051 |
TIMEOUT_ON_RESOURCE |
在等待資源時發生超時 |
ORA-00001 |
DUP_VAL_ON_INDEX |
試圖破壞一個惟一性限制 |
ORA-01017 |
LOGIN_DENIED |
無效的用戶名/口令 |
ORA-01476 |
ZERO_DIVIDE |
試圖被零除 |
ORA-01722 |
INVALID_NUMBER |
轉換一個數字失敗 |
ORA-06500 |
STORAGE_ERROR |
內存不夠或內存被破壞觸發的內部錯誤 |
ORA-06502 |
VALUE_ERROR |
賦值操做,變量長度不足,觸發該異常 |
ORA-06504 |
ROWTYPE_MISMATCH |
宿主遊標變量與PL/SQL變量有不兼容行類型 |
ORA-06531 |
COLLECTION_IS_NULL |
試圖給沒有初始化的嵌套表變量或者VARRY變量賦值 |
ORA-06532 |
SUBSCRIPT_OUTSIDE_LIMIT |
對嵌套或VARRAY索引使用了負數 |
ORA-06533 |
SUBSCRIPT_BEYOND_COUNT |
對嵌套或VARRAY索引的引用大於集合中元素的個數 |
預約義異常的示例以下所示:
SYS@lhrdb> SET SERVEROUTPUT ON
SYS@lhrdb> DECLARE
2 V_ENAME SCOTT.EMP.ENAME%TYPE;
3 V_SAL SCOTT.EMP.SAL%TYPE;
4 V_INPUT SCOTT.EMP.SAL%TYPE := 100;
5 BEGIN
6 SELECT ENAME, SAL INTO V_ENAME, V_SAL FROM SCOTT.EMP WHERE SAL = V_INPUT;
7 DBMS_OUTPUT.PUT_LINE(V_ENAME || ',' || V_SAL);
8 EXCEPTION
9 WHEN NO_DATA_FOUND THEN
10 DBMS_OUTPUT.PUT_LINE('沒找到任何數據');
11 WHEN TOO_MANY_ROWS THEN
12 DBMS_OUTPUT.PUT_LINE('找到多行數據,建議使用遊標');
13 WHEN OTHERS THEN
14 DBMS_OUTPUT.PUT_LINE('出錯了!!');
15 DBMS_OUTPUT.PUT_LINE(SQLCODE || ',' || SQLERRM);
16
17 END;
18 /
沒找到任何數據
PL/SQL procedure successfully completed.
2、非預約義異常(Non Predefined)
非預約義異常用於處理預約義異常不能處理的異常,即其它標準的Oracle錯誤。使用預約義異常只能處理系統預約義的20多個Oracle錯誤,而當使用PL/SQL開發應用程序時,可能會遇到其它的一些Oracle錯誤。例如,在PL/SQL塊中執行DML語句時,違反了約束規定等等。在這樣的狀況下,就可使用非預約義異常來處理。
Oracle提供了2個函數SQLCODE和SQLERRM用於返回錯誤信息:
l SQLCODE:返回錯誤代碼
l SQLERRM:返回與錯誤代碼關聯的消息
這樣就能夠在錯誤日誌表中記錄程序在執行過程當中發生的錯誤信息了。
非預約義異常的示例以下所示:
SYS@lhrdb> SET SERVEROUTPUT ON
SYS@lhrdb> DECLARE
2 FK_EXCEPTION EXCEPTION; --定義一個異常類型的變量
3 PRAGMA EXCEPTION_INIT(FK_EXCEPTION, -2292); --將該變量和指定的錯誤碼綁定
4 V_ERROR_CODE NUMBER;
5 V_ERROR_MESSAGE VARCHAR2(255);
6 BEGIN
7 DELETE FROM SCOTT.DEPT WHERE DEPTNO = 20;
8 EXCEPTION
9 WHEN FK_EXCEPTION THEN
10 --能夠用異常類型的名字進行異常的捕獲
11 DBMS_OUTPUT.PUT_LINE('找到子記錄,刪除失敗');
12 WHEN OTHERS THEN
13 ROLLBACK;
14 DBMS_OUTPUT.PUT_LINE(SQLCODE || ',' || SQLERRM);
15 END;
16 /
找到子記錄,刪除失敗
PL/SQL procedure successfully completed.
3、自定義異常(User_define)
自定義異常用於處理與Oracle錯誤無關的其它狀況。對這種異常狀況的處理,須要用戶在程序中定義,而後顯式地在程序中將其觸發。
預約義異常和自定義異常都是與Oracle錯誤相關的,而且出現的Oracle錯誤會隱含地觸發相應的異常;而自定義異常與Oracle錯誤沒有任何關聯,它是由開發人員爲特定狀況所定義的異常。當與一個異常相關的錯誤出現時,就會隱含觸發該異常。用戶定義異常是經過顯式使用RAISE語句來觸發。當觸發一個異常時,控制程序就轉到異常塊部分,執行錯誤處理代碼。
自定義異常的示例以下所示:
SYS@lhrdb> SET SERVEROUTPUT ON
SYS@lhrdb> DECLARE
2 V_SAL SCOTT.EMP.SAL%TYPE;
3 V_ENAME SCOTT.EMP.ENAME%TYPE;
4 V_EMPNO SCOTT.EMP.EMPNO%TYPE := 6;
5 SALARY_EXCEPTION EXCEPTION; --定義異常的類型(名字)
6 BEGIN
7 SELECT ENAME, SAL INTO V_ENAME, V_SAL FROM SCOTT.EMP WHERE EMPNO = V_EMPNO;
8 IF V_SAL < 1500 THEN
9 V_SAL := V_SAL + 100;
10 DBMS_OUTPUT.PUT_LINE(V_ENAME || '漲工資後:' || V_SAL);
11 ELSE
12 RAISE SALARY_EXCEPTION; --拋出自定義的異常
13 END IF;
14 EXCEPTION
15 WHEN SALARY_EXCEPTION THEN
16 --捕獲自定義的異常
17 DBMS_OUTPUT.PUT_LINE('薪金沒有達到最低水平,不須要漲工資');
18 WHEN NO_DATA_FOUND THEN
19 DBMS_OUTPUT.PUT_LINE('沒有找到' || V_EMPNO || '編碼的員工');
20 WHEN OTHERS THEN
21 DBMS_OUTPUT.PUT_LINE(SQLCODE || ',' || SQLERRM);
22 END;
23 /
沒有找到6編碼的員工
PL/SQL procedure successfully completed.
詳細內容能夠添加麥老師微信或QQ私聊。
● 本文做者:小麥苗,只專一於數據庫的技術,更注重技術的運用
● 做者博客地址:http://blog.itpub.net/26736162/abstract/1/
● 本系列題目來源於做者的學習筆記,部分整理自網絡,如有侵權或不當之處還請諒解
● 版權全部,歡迎分享本文,轉載請保留出處
● QQ:646634621 QQ羣:618766405
● 題目解答如有不當之處,還望各位朋友批評指正,共同進步
長按下圖識別二維碼或微信掃描下圖二維碼來關注小麥苗的微信公衆號:xiaomaimiaolhr,學習最實用的數據庫技術。
本文分享自微信公衆號 - DB寶(lhrdba)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。