ORACLE異常處理總結
2024-08-29 13:53:35
供稿:網友
1:預定義異常 用于處理常見的Oracle錯誤
2:非預定義異常 用于處理預定義異常所不能處理的Oracle錯誤
3:自定義異常 用于處理于Oracle錯誤無關的其他情況
異常處理部分是以關鍵字EXCEPTION開始的,語法如下:
EXCEPTION
WHENexception_NameTHEN --exception_Name為異常的名字
statement1;
WHENOTHERSTHEN
statement1;
異常處理部分從關鍵字EXCEPTION開始,在異常處理部分使用WHEN字句捕捉各種異常,如果有其他未預定義到的異常,使用WHENOTHERSTHEN字句進行捕捉和處理。
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。
一:首先的定義部分定義異常;
二:使用progma exception_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
UPDATEempSETdeptno=&dnoWHEREempno=&eno;
EXCEPTION
WHENe_integrityTHEN --3、捕捉處理
DBMS_OUTPUT.PUT_LINE(‘該部門不存在’);
END;
--3、處理自定義異常
預定義異常和非預定義異常都與Oracle錯誤有關,并且當出現Oracle錯誤時會隱含觸發相應異常;
而自定義異常與Oracle錯誤沒有任何關聯,它是由開發人員為特定情況所定義的異常。
當使用自定義異常時,
一:需要在定義部分(DECLARE)定義異常,
二:再執行部分(BEGIN)觸發異常(使用RAISE語句),
三:在異常處理部分(EXCEPTION)捕捉并處理異常。
declare
myexceptionexception;
begin
if 1=0 then
raisemyexception;
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
Whenothersthen
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(默認值)則會替代先前所有錯誤。
IFproduct_not_foundTHEN
RAISE_APPLICATION_ERROR(-20123,'Invald product code'TRUE);
ENDIF;
--5、plsql編譯警告:
plsql警告可以分為四類:
severe:用于檢查可能出現的不可預料或者錯誤結果,例如參數的別名問題;
performance:用于檢查可能引起的性能問題,例如執行insert操作時為number列提供了varchar2類型數據;
informational:用于檢查子程序中的死代碼;
all:用于檢查所有警告。
為了數據庫可以在編譯plsql子程序時發出警告信息,需要設置初始化參數plsql_warnings。這個參數不僅可以在系統級或者會話級設置,也可以在alter procedure命令中設置。
Alter{system|session|procedure}
setplsql_warnings=
’{enable|disable:{all|performance|severe|informational}}’;
為了檢查是否存在對應警告信息,必須先激活警告檢查,然后重新編譯子程序,最后使用show errors命令顯示警告錯誤。
createorreplaceproceduremy_test
is
begin
if1=0then
dbms_output.put_line('test');
endif;
end;
SQL>alterproceduremy_test compile plsql_warnings='enable:all';
Procedurealtered
SQL>show errors;
ErrorsforPROCEDURESYS.MY_TEST:
LINE/COL ERROR
-------- -------------------------
10/5 PLW-06002:無法執行的代碼
--6、定義Exception時要注意的一些事項
當異常發生時,在塊的內部沒有該異常處理器時,控制將轉到或傳播到上一層塊的異常處理部分。
沒有處理的異常將沿檢測異常調用程序傳播到外層,當異常被處理并解決或到達程序最外層傳播停止。在聲明部分拋出的異常將控制轉到上一層的異常部分。
用戶必須在獨立的WHEN子串中為每個異常設計異常處理代碼,WHEN OTHERS子串必須放置在最后面作為缺省處理器處理沒有顯式處理的異常。當異常發生時,控制轉到異常部分,ORACLE查找當前異常相應的WHEN..THEN語句,捕捉異常,THEN之后的代碼被執行,如果錯誤陷阱代碼只是退出相應的嵌套塊,那么程序將繼續執行內部塊END后面的語句。如果沒有找到相應的異常陷阱,那么將執行WHEN OTHERS。在異常部分WHEN子串沒有數量限制。