【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/

● 本系列題目來源於作者的學習筆記,部分整理自網絡,若有侵權或不當之處還請諒解

● 版權所有,歡迎分享本文,轉載請保留出處

● 題目解答若有不當之處,還望各位朋友批評指正,共同進步