【DB筆試面試445】Oracle中的異常可以分為哪幾類?
- 2019 年 10 月 11 日
- 筆記
Oracle中的異常可以分為哪幾類?
答案部分
異常(EXCEPTION)處理是用來處理正常執行過程中未預料到的事件,包括程序塊的異常處理、預定義的錯誤和自定義錯誤。如果PL/SQL程序塊一旦產生異常,而程序並沒有指出如何處理,那麼程序就會自動終止運行。
異常處理部分一般放在PL/SQL程序體的後半部分,結構如下所示:
EXCEPTION
WHEN first_exception THEN <code to handle first exception >
WHEN second_exception THEN <code to handle second exception >
WHEN OTHERS THEN <code to handle OTHERS exception >
對於異常處理,需要注意以下幾點內容:
(1)異常處理可以按任意次序排列,但OTHERS必須放在最後。
(2)當程序出現異常時,程序立即暫停工作,跳轉到EXCEPTION部分。使用WHEN … THEN來處理系統定義的異常。使用WHEN OTHERS THEN處理未定義的異常。
(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.
About Me:小麥苗
● 本文作者:小麥苗,只專註於數據庫的技術,更注重技術的運用
● 作者博客地址:http://blog.itpub.net/26736162/abstract/1/
● 本系列題目來源於作者的學習筆記,部分整理自網絡,若有侵權或不當之處還請諒解
● 版權所有,歡迎分享本文,轉載請保留出處
● 題目解答若有不當之處,還望各位朋友批評指正,共同進步