Oracle異常處理總結

爲了處理PL/SQL應用程序的各種錯誤,開發人員可以使用各種類型的異常。
Oracle提供了
1:預定義異常
用於處理常見的Oracle錯誤
2:非預定義異常
用於處理預定義異常所不能處理的Oracle錯誤
3:自定義異常
用於處理於Oracle錯誤無關的其他情況
異常處理部分是以關鍵字EXCEPTION開始的,語法如下:
  EXCEPTION
    WHEN  exception_Name THEN  --exception_Name爲異常的名字
      statement1;
    WHEN OTHERS THEN
  statement1;
   


異常處理部分從關鍵字EXCEPTION開始,在異常處理部分使用WHEN字句捕捉各種異常,如果有其他未預定義到的異常,使用WHEN OTHERS THEN字句進行捕捉和處理。
1、 處理預定義異常,這是系統預定的21種類型
  錯誤代碼是負整數,如-51
     

   
  Access_info_null(ora-06530)
     當訪問沒有初始化的對象時觸發。
   
  Case_not_found(ora-06592)
     case過程中when後沒有包含必要的條件分支並且沒有else子句,則會觸發本異常。
   
  Collection_is_null(06531)
     訪問未初始化的集合元素(嵌套表或者varray)。
   
  Cursor_already_open(ora-06511)
     重新打開已經打開的遊標。
   
  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返回超過一行數據時。
   
  Zero_divide(ora-01476)
     0作爲被除數時。
   
  Subscript_beyond_count(ora-06533)
     使用嵌套表或者varray集合時,如果引用下標超過last。
   
  Subscript_outside_limit(ora-06532)
     使用嵌套表或varray集合時,如果引用下標小於first。
   
  Value_error(ora-06502)
     在執行賦值操作時,如果變量長度不足以容納實際數據。
   
  Login_denied(ora-01017)
     連接數據庫時提供了不正確的用戶名或口令。
   
  Not_logged_on(ora-01012)
     在程序沒有連接到oracle數據庫時執行plsql代碼則會觸發。
   
  Program_error(ora-06501)
     plsql內部問題。
   
  Rowtype_mismatch(ora-06504)
     執行賦值操作時,如果宿主遊標變量和PLSQL遊標變量返回類型不兼容時。
   
  Self_is_null(ora-30625)
     使用對象類型時,如果在null實例上調用成員方法。
   
  Storage_error(ora-06500)
     超出內存空間或者內存被損壞。
   
  Sys_invalid_rowid(ora-01410)
     無效字符串企圖轉換爲rowid類型時。
   
  Timeout_on_resource(ora-00051)
     等待資源時出現超時錯誤。
   


2、處理非預定義異常
使用非預定義異常包括三步:
一:在定義部分定義異常名,
二:在異常和Oracle錯誤之間建立關聯,
三:在異常處理部分捕捉並處理異常。


當定義Oracle錯誤和異常之間的關聯關係時,需要使用僞過程EXCEPTION_INIT。


一:首先的定義部分定義異常;
二:使用progmaexception_init(exception_name,exception_number) 在異常和oracle錯誤之間建立關聯,
    這時要求用戶知道可能出現的錯誤號(異常函數sqlcode、sqlerrm和raise_application_error);
三:最終在異常處理部分捕捉並處理異常。

 


下面以更新特定僱員的部門號,並處理ORA-02291錯誤爲例,說明使用非預定義異常的方法。示例如下:


  DECLARE
    e_integrity EXCEPTION;  --1、定義部分
    PRAGMA EXCEPTION_INIT (e_integrity, -2291);  --2、建立關聯關係
  BEGIN
    UPDATE  emp SET deptno=  &dno WHERE  empno = &eno;
  EXCEPTION
    WHEN  e_integrity THEN  --3、捕捉處理
      DBMS_OUTPUT.PUT_LINE(‘該部門不存在’);
  END;
  

   
--3、處理自定義異常
預定義異常和非預定義異常都與Oracle錯誤有關,並且當出現Oracle錯誤時會隱含觸發相應異常;
而自定義異常與Oracle錯誤沒有任何關聯,它是由開發人員爲特定情況所定義的異常。


當使用自定義異常時,
一:需要在定義部分(DECLARE)定義異常,
二:再執行部分(BEGIN)觸發異常(使用RAISE語句),
三:在異常處理部分(EXCEPTION)捕捉並處理異常。


  declare
   myexception exception;
  begin
  
if
1=0
then
  
raise myexception;
  
endif; 
  exception
  
when

myexception 
then
       dbms_output.put_line('asdf');
  end;
   
注意:不能在同一個block中描述EXCEPTION兩次,但是可以描述一個exception在兩個不同的block中。異常(exception)是有作用域的,子塊的異常不能被當前塊所捕捉,

 

--4、使用異常函數:
Oracle內置函數sqlcode和sqlerrm主要用在others處理器中,分別用來返回oracle的錯誤代碼和錯誤消息。
一般情況下sqlcode返回負數標識的oracle錯誤代碼,除非錯誤
爲‘ora-01403:no data found’,此時對應的sqlcode爲+100,
對於用戶自定義的異常,sqlcode返回+1,如果沒有異常被觸發,sqlcode返回0。
  Begin
  Exception
   When  others then
      Dbms_output.put_line(sqlcode||sqlerrm(sqlcode));
  End;
   

 


Oracle過程raise_application_error用於在plsql應用程序中自定義錯誤消息。
注意該過程只能在數據庫端的子程序(過程、函數、包、觸發器)中使用,而不能在匿名塊和客戶端的子程序中使用。
語法爲raise_application_error(error_number,message[,[true|false]]);
其中

error_number用於定義錯誤號,該錯誤號必須在-20000到-20999之間的負整數;
message用於指定錯誤消息,並且該消息的長度不
能超過2048字節;
第三個參數如果爲true,則該錯誤會被放在先前錯誤堆棧中,如果爲false(默認值)則會替代先前所有錯誤。
  IF product_not_found THEN
               RAISE_APPLICATION_ERROR(-20123,'Invald product code'  TRUE);
  END IF;
   

 


--5、plsql編譯警告:
plsql警告可以分爲四類:
severe:用於
檢查可能出現的不可預料或者錯誤結果,例如參數的別名問題;
performance:用於檢查可能引起的性能問題,例如執行insert操作時爲 number列提供了varchar2類型數據;
informational:用於檢查子程序中的死代碼;
all:用於檢查所有警告。


爲了數據庫可以在編
譯plsql子程序時發出警告信息,需要設置初始化參數plsql_warnings。這個參數不僅可以在系統級或者會話級設置,也可以在alter procedure命令中設置。
  Alter {system|session|procedure} 
  set plsql_warnings=
  
’{enable|disable:{all |performance|severe|informational}}’;
   


爲了檢查是否存在對應警告信息,必須先激活警告檢查,然後重新編譯子程序,
最後使用show errors命令顯示警告錯誤。
  create or  replace procedure  my_test
  is
  begin
   if  1=0 then
      dbms_output.put_line('test');
   endif; 
  end;
  SQL>  alter procedure  my_test compile plsql_warnings = 'enable:all';
  

  Procedure altered
   SQL>  show errors;
  Errors for  PROCEDURE SYS.MY_TEST:
   LINE/COL ERROR
  --------  -------------------------
  10/5      PLW-06002: 無法執行的代碼
   


--6、定義Exception時要注意的一些事項
當異常發生時,在塊的內部沒有該異常處理器時,控制將轉到或傳播到上一層塊的異常處理部分。
沒有處理的異常將沿檢測異常調用程序傳播到外層,當異常被處理並解決或到達程序最外層傳播停止。在聲明部分拋出的異常將控制轉到上一層的異常部分。


用戶必須在獨立的WHEN子串中爲每個異常設計異常處理代碼,WHEN OTHERS子串必須放置在最後面作爲缺省處理器處理沒有顯式處理的異常。當異常發生時,控制轉到異常部分,ORACLE查找當前異常相應的WHEN..THEN語句,捕捉異常,THEN之後的代碼被執行,如果錯誤陷阱代碼只是退出相應的嵌套塊,那麼程序將繼續執行內部塊END後面的語句。如果沒有找到相應的異常陷阱,那麼將執行WHEN OTHERS。在異常部分WHEN 子串沒有數量限制。
  EXCEPTION
  
WHEN inventory_too_low THEN
  
      ......
  
WHEN discontinued_item THEN
  
      ......
  
WHEN zero_divide THEN
  
      ......
  
WHEN OTHERS THEN
  
      ...... 


oracle預定義的異常列表
2008-10-30 16:06
命名的系統異常         產生原因 
ACCESS_INTO_NULL         未定義對象 
CASE_NOT_FOUND         CASE 中若未包含相應的 WHEN ,並且沒有設置 ELSE 時 
COLLECTION_IS_NULL         集合元素未初始化 
CURSER_ALREADY_OPEN         遊標已經打開 
DUP_VAL_ON_INDEX         唯一索引對應的列上有重複的值 
INVALID_CURSOR         在不合法的遊標上進行操作 
INVALID_NUMBER         內嵌的 SQL 語句不能將字符轉換爲數字 
NO_DATA_FOUND         使用 select into 未返回行,或應用索引表未初始化的元素時 
TOO_MANY_ROWS         執行 select into 時,結果集超過一行 
ZERO_DIVIDE         除數爲 0 
SUBSCRIPT_BEYOND_COUNT         元素下標超過嵌套表或 VARRAY 的最大值 
SUBSCRIPT_OUTSIDE_LIMIT         使用嵌套表或 VARRAY 時,將下標指定爲負數 
VALUE_ERROR         賦值時,變量長度不足以容納實際數據 
LOGIN_DENIED         PL/SQL 應用程序連接到 oracle 數據庫時,提供了不正確的用戶名或密碼 
NOT_LOGGED_ON         PL/SQL 應用程序在沒有連接 oralce 數據庫的情況下訪問數據 
PROGRAM_ERROR         PL/SQL 內部問題,可能需要重裝數據字典& pl./SQL 系統包 
ROWTYPE_MISMATCH         宿主遊標變量與 PL/SQL 遊標變量的返回類型不兼容 
SELF_IS_NULL         使用對象類型時,在 null 對象上調用對象方法 
STORAGE_ERROR         運行 PL/SQL 時,超出內存空間 
SYS_INVALID_ID         無效的 ROWID 字符串 
TIMEOUT_ON_RESOURCE         Oracle 在等待資源時超時

=============================================================

BEGIN
《PL/SQL塊》;
Exception
when no_data_found then --沒有找到數據
《響應命令》;
when too_many_rows then --返回多行,隱式光標每次只能檢索一行數據
《響應命令》;
when invalid_number then --字符向數字轉換失敗
《響應命令》;
when zero_divide then --被零除
《響應命令》;
when dup_val_on_index then --向唯一索引中插入重複數據
《響應命令》;
when invalid_cursor then --非法遊標操作
《響應命令》;
when value_error then --數字的,數據轉換,截字符串或強制性的錯誤
《響應命令》;
when others then --發生其它任何錯誤
null; --選擇一:什麼也不做,就當錯誤沒發生
raise form_trigger_failure; --選擇二:掛起當前程序
END;


常用預定義例外
EXCEPTION
WHEN CURSOR_ALREADY_OPEN THEN -- ORA-06511 SQLCODE = -6511 遊標已經打開
..WHEN DUP_VAL_ON_INDEX THEN -- ORA-00001 SQLCODE = -1 向唯一索引中插入重複數據
..WHEN INVALID_CURSOR THEN -- ORA-01001 SQLCODE = -1001 非法遊標操作
..WHEN INVALID_NUMBER THEN -- ORA-01722 SQLCODE = -1722 字符向數字轉換失敗
..WHEN LOGIN_DENIED THEN -- ORA-01017 SQLCODE = -1017 

..WHEN NO_DATA_FOUND THEN -- ORA-01403 SQLCODE = +100 沒有找到數據
..WHEN NOT_LOGGED_ON THEN -- ORA-01012 SQLCODE = -1012 
..WHEN PROGRAM_ERROR THEN -- ORA-06501 SQLCODE = -6501 程序錯誤
..WHEN STORAGE_ERROR THEN -- ORA-06500 SQLCODE = -6500
..WHEN TIMEOUT_ON_RESOURCE THEN -- ORA-00051 SQLCODE = -51

..WHEN TOO_MANY_ROWS THEN -- ORA-01422 SQLCODE = -1422 返回多行
..WHEN TRANSACTION_BACKED_OUT THEN -- ORA-00061 SQLCODE = -61

..WHEN VALUE_ERROR THEN -- ORA-06502 SQLCODE = -6502 數值轉換錯誤
..WHEN ZERO_DIVIDE THEN -- ORA-01476 SQLCODE = -1476 被零除
..WHEN OTHERS THEN -- 其它任何錯誤的處理
..END; 

 

 

 

本文來自:http://blog.csdn.net/zjhiphop2006/archive/2010/06/01/5637578.aspx

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章