預定義錯誤型別

realkid4發表於2011-02-12

今天一個朋友在MSN上問一個問題。他在PL/SQL程式碼的時候,需要捕獲主鍵插入重複異常。他說,有沒有類似於“NO_DATA_FOUND”型別的常量資訊來指代這種錯誤,然後好進行錯誤處理。

 

這個問題涉及到Oracle PL/SQL程式碼的錯誤處理機制,以及預定義的錯誤資訊,這裡簡單說一下。

 

OraclePL/SQL語言作為一種獨立語言出現,極大彌補了純SQL語句上的缺陷和不足。加入過程化因素,使得在資料庫端實現複雜業務邏輯的目標得以實現。作為一種獨立程式語言,錯誤異常處理(Error/Exception Handle)是一個不可或缺的部分。

 

 

異常Exception發生的原因有很多,比如設計缺陷、程式碼錯誤、業務資料缺陷和軟硬體故障等等。在開發階段預想到所有可能發生的異常是不可能的,但是作為開發人員,我們是可以捕獲和處理異常的。正確捕獲和處理異常非常重要,特別是進行一些關鍵的DML操作,要保證資料和業務的完整性。

 

Oracle中的Exception有兩種,一種是內部定義的(也成為執行時異常)、另一種是使用者定義異常。內部異常透過編號進行標誌,例如ORA_XXXX。內部錯誤是由Oracle內部定義,並且由Oracle自己去檢測激發。一些常見的內部異常,是有自己的預定義名稱的。如我們常見的TOO_MANY_ROWSZERO_DIVIDE等。朋友的意思也就是找到匹配“主鍵重複”錯誤的預定義名稱。

 

對異常的處理,首先談到的是異常的檢測。在目前流行的語言(如JavaC#)中,都是採用類似“try…catch…finally”的結構。在一段程式碼中檢測異常,當發生的時候,透過層層檢驗捕捉。最後使用finally進行資源回收。

 

 

Oraclepl/sql同樣採用了這種類似的結構。是使用一個begin---end塊包裹,如下:

 

set serveroutput on size 10000;

declare

  n_totalsal number :=1000;

  n_number number :=0;

  n_price number;

begin

  n_price := n_totalsal/n_number;

exception

  when too_many_rows then

     dbms_output.put_line('Too Many Data Found !');

  when zero_divide then

     dbms_output.put_line('zero_divide');

  when others then

     dbms_output.put_line('Others');       

end;

/

 

這段程式碼,最終生成異常,並且被zero_divide所攔截。匿名塊返回結果為:

 

SQL>

 

zero_divide

 

PL/SQL procedure successfully completed

 

 

Oracle中,同樣存在一些像too_many_rows這種預定義的錯誤資訊。下面從參考文獻中找出歸納。

 

異常名稱

ORA ERROR

SQLCODE

含義和丟擲點

ACCESS_INTO_NULL

06530

-6530

當程式給一個未初始化物件的屬性賦值時候,丟擲;

CASE_NOT_FOUND

06592

-6592

使用Case語句的時候,沒有使用else字句,並且when的情況不能覆蓋;

COLLECTION_IS_NULL

06531

-6531

當呼叫一個未初始化陣列或者集合物件的非Exists方法,或者對一個為未初始化陣列集合賦值;

CURSOR_ALREADY_OPEN

06511

-6511

程式試圖開啟一個已經開啟的cursor。開啟遊標只能是針對一個關閉的遊標進行;

DUP_VAL_ON_INDEX

00001

-1

違反索引唯一約束;

INVALID_CURSOR

01001

-1001

對遊標進行非法操作,比如關閉一個處在非開啟狀態的遊標;

INVALID_NUMBER

01722

-1722

數字型別轉換錯誤;

LOGIN_DENIED

01017

 

非法使用者名稱密碼登入;

NO_DATA_FOUND

01403

+100

使用select into的時候,如果沒有返回值;

NOT_LOGGED_ON

01012

-1012

在沒有登入的情況下,呼叫資料庫操作命令;

PROGRAM_ERROR

06501

-6501

PL/SQL發生了內部錯誤;

ROWTYPE_MISMATCH

06504

-6504

本地遊標和PL/SQL遊標返回型別不匹配;

SELF_IS_NULL

30625

-30625

試圖呼叫一個沒有初始化的物件的方法成員,因為關鍵字SELF表示的是物件的自生(是內建引數),在呼叫時候總是第一個傳遞給方法成員。

STORAGE_ERROR

06500

-6500

PL/SQL程式碼超出記憶體或者記憶體崩潰;

SUBSCRIPT_BEYOND_COUNT

06533

-6533

訪問陣列、集合的時候,地址index超過下標界限(過上界);

SUBSCRIPT_OUTSIDE_LIMIT

06532

-6532

訪問陣列、集合的時候,地址index超過下標界限(過下界);

SYS_INVALID_ROWID

01410

-1410

將一個字串轉化為rowid的時候,發現非法;

TIMEOUT_ON_RESOUCE

00051

-51

當資料庫等待一個執行資源的時候,操作cursor超時;

TOO_MANY_ROWS

01422

-1422

Select into語句返回了多條記錄;

VALUE_ERROR

06502

-6502

數字演算法、轉換或者源於長度限制的錯誤;

ZERO_DIVIDE

01476

-1476

除零;

 

 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/17203031/viewspace-687040/,如需轉載,請註明出處,否則將追究法律責任。

相關文章