程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> Oracle數據庫 >> Oracle數據庫基礎 >> Oracle 異常處理 教程

Oracle 異常處理 教程

編輯:Oracle數據庫基礎
 

說說異常

在總結PL/SQL的基礎知識時,說到了以下內容:

[declare]
    -- declaration statements
    i integer;begin
    -- executable statements

[exception]
    -- exception statements
end;

對於其中的exception沒有進行詳細的總結,那麼exception在Oracle又是怎麼樣的呢?出現了exception又要如何處理呢?這篇文章就對Oracle中的exception進行詳細的總結。

 

Oracle預定義異常

在Oracle中,異常分為以下兩類:

  • Oracle預定義異常
  • 用戶自定義異常

在Oracle中預定義的異常如下表所示:

異常名稱 錯誤代碼 產生原因 ACCESS_INTO_NULL 06530 為一個未初始化對象的屬性賦值 CASE_NOT_FOUND 06592 在CASE過程中,WHEN後沒有包含必要的條件分支並且沒有ELSE子句 COLLECTION_IS_NULL 06531 使用未初始化的集合元素 CURSOR_ALREADY_OPEN 06511 游標已經打開 DUP_VAL_ON_INDEX 00001 在具有唯一索引的列上插入一個重復值 INVALID_CURSOR 01001 在無效的游標上進行操作 INVALID_NUMBER 01722 在一個SQL語句中,由於字符串並不代表一個有效的數字,導致字符串向數字轉換時會發生錯誤。(在過程化語句中,會拋出異常VALUE_ERROR。)當FETCH語句的LIMIT子句表達式後面不是一個正數時,這個異常也會被拋出。 LOGIN_DENIED 01017 使用錯誤的用戶名或密碼登陸數據庫 NO_DATA_FOUND 01403 SELECT INTO未返回行,或者程序引用了嵌套表中一個已經刪除的元素,或者引用表中一個為初始化的元素 NOT_LOGGED_ON 01012 沒有連接到數據庫 PROGRAM_ERROR 06501 PL/SQL內部錯誤 ROWTYPE_MISMATCH 06504 賦值語句中使用的主游標變量和PL/SQL游標變量的類型不兼容 SELF_IS_NULL 30625 調用一個未被實例化的對象的成員方法,內置的SELF參數總是指向這個對象,SELF會作為函數的第一個參數傳遞到這個成員方法,就好比C++中的this STORAGE_ERROR 06500 內存溢出或者內存不足 SUBSCRIPT_BEYOND_COUNT 06533 程序引用一個嵌套表或變長數組元素,但使用的下標索引超過嵌套表或變長數組元素總個數 SUBSCRIPT_OUTSIDE_LIMIT 06532 程序引用一個嵌套表或變長數組,但使用的下標索引不在合法的范圍內 SYS_INVALID_ROWID 01410 從字符串向ROWID轉換發生錯誤,因為字符串並不代表一個有效的ROWID TIMEOUT_ON_RESOURCE 00051 當Oracle請求資源時,發生超時現象 TOO_MANY_ROWS 01422 SELECT INTO返回的行數太多 VALUE_ERROR 06502 發生算術、轉換、截位或長度約束錯誤。例如,當我們的程序把一個字段的值放到一個字符變量中時,如果值的長度大於變量的長度,PL/SQL就會終止賦值操作並拋出異常VALUE_ERROR。在過程化語句中,如果字符串向數字轉換失敗,異常VALUE_ERROR就會被拋出(在SQL語句中,異常INVALID_NUMBER會被拋出) ZERO_DIVIDE 01476 程序嘗試除以0

 

用戶自定義異常

和其它語言一樣,我們也可以定義我們滿足我們自己要求的異常,自定義一樣的語法格式如下:

PRAGMA EXCEPTION_INIT(exception_name, -Oracle_error_number);
  • exception_name:異常的名字
  • Oracle_error_number:錯誤編號,以符號’-‘開始,范圍從-20000~-20999
 

觸發異常

定義了那麼多異常,那麼在程序中如何拋出異常呢?在Oracle中有以下三種方式觸發異常:

  • 由Oracle自動觸發異常
  • 使用RAISE語句手工觸發
  • 調用存儲過程RAISE_APPLICATION_ERROR手工觸發

下面的代碼將演示Oracle自動觸發異常:

-- Created on 2015-7-14 by JellyThink 
declare 
    iA NUMBER(2) := 10;begin
    iA := iA / 0; -- Oracle自動觸發異常
    dbms_output.put_line(iA);
exception
    when ZERO_DIVIDE then
        dbms_output.put_line('Error Code:' || SQLCODE || ' ' || SQLERRM);
    when others then
        dbms_output.put_line('Others Exception');end;

下面的代碼將演示使用RAISE語句手工觸發異常:

-- Created on 2015-7-14 by JellyThink 
declare 
    myException EXCEPTION;begin
    RAISE myException; -- RAISE手工觸發異常
exception
    when others then
        dbms_output.put_line('Others Exception');end;

下面的代碼將演示使用RAISE_APPLICATION_ERROR觸發異常:

-- Created on 2015-7-14 by JellyThink 
declare 
    myException EXCEPTION;
    PRAGMA EXCEPTION_INIT(myException, -20009);begin
    RAISE_APPLICATION_ERROR(-20009, 'Exception'); -- 這裡可以指定異常信息
exception
    when myException then
        dbms_output.put_line('myException Exception');end;
 

異常傳遞

先來看看下面這段代碼:

-- Created on 2015-7-15 by JellyThink 
declare 
    i Number;begin
    i := 10;
    declare
    begin
        i := i / 0; -- 嵌套塊中拋出異常
    /*exception
        when ZERO_DIVIDE then
            dbms_output.put_line('Error');*/ -- 嵌套塊不處理這個異常
    end;
exception
    -- 在這裡處理子塊拋出的異常
    when ZERO_DIVIDE then
        dbms_output.put_line('Error Code:' || SQLCODE || ' ' || SQLERRM);
    when others then
        dbms_output.put_line('Error Code:' || SQLCODE || '  ' || SQLERRM);end;

在一個塊中,只能有一個異常處理部分,在不同的塊中,可以定義多個異常處理部分。父塊中可以定義異常處理,子塊中也可以定義自己的異常處理。當一個子塊的異常發生時,如果在子塊的異常處理部分沒有進行處理,該異常會傳遞到父塊中,如果父塊中沒有對應的異常處理部分,那麼這個異常會繼續向上傳遞。

 

總結

異常的處理在一個程序中是必不可少的,也是你的代碼走向完美的一個必要的部分。只有熟悉的掌握了異常處理,才能更好的服務於你的代碼。想想我們現在系統中的存儲過程,都沒有異常處理,哦,誰寫的,我保證不打死你。

 
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved