pl/sql
提供了強大而靈活的手段來捕捉和處理程序產生的異常,從而使
oracle
的用戶遠離一些令人煩惱的
bug
。
?
pl/sql
異常處理的概念和術語
?
在
oracle
中所有的錯誤都被認為是不應該發生的異常。一個異常可能是以下
3
種情況的一種:
u??????
由系統產生的錯誤(“
out of memory
”或“
duplicate value in index
”)
u??????
用戶行為導致的錯誤
u??????
應用程序給用戶的一個警告
pl/sql
用一種異常句柄的結構來捕捉和響應錯誤。正是有了異常句柄的存在,我們能很方便的分離異常處理代碼與可執行代碼。與線性的代碼相比,為了處理異常,異常句柄提供了一種類似事件驅動的模式;換句話說,就是不管一種特定的錯誤在何時何地發生,它都將被同一個代碼處理。
當一個錯誤出現后,無論它是系統還是程序產生的,都將導致一個異常。之后,可執行程序被中斷,控制權轉移給異常處理代碼。處理完異常后,程序將不會回到先前被中斷的位置,相反的,控制權被交給了當前程序的外圍模塊(可能是程序,也可能是系統)。
?????? procedure jimmy
?????? is
??????
?????? new_value varchar(35)
?????? begin
|--------new_value:=old_value || ‘-new’;
|????????? if new_value like ‘like%’
|????????? then
|????????? ?????? …..
|????????? end if;
|?? exception
|-----
à
?????? when value_error
????????????? then
?????????????
?????? …..
?????? end;
因為
old_value
是一個未被定義的變量,所以將產生一個錯誤,并將給異常處理模塊處理。
?
從異常的可應用范圍出發,可將異常分為兩類:
系統異常:
由
oracle
定義并由
pl/sql runtime
引擎在檢測到錯誤時產生的異常。一些系統異常有名字,比如
NO_DATA_FOUND
,然而大多數的異常僅僅只有數字編號和描述。這些異常無論在哪個
pl/sql
中程序都能被應用。
共有
21
個命名的系統異常:
命名的系統異常
|
產生原因
|
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 iotn
時,返回超過一行
|
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
在等待資源時超時
|
?
由程序員定義的異常:
程序員在程序中定義的異常,它只是在特定的程序種有效。可以使用
EXCEPTION_INT
這個
pragma
將一個無名字的系統異常與一個程序員定義的名字相關聯。或者用
RAISE_APPLICATION_ERROE
來自己定義一個異常的數字編號和描述。
?
按異常生成方式可分為:
預定義異常:
??????
就是上面表中的
21
種有名字的系統異常。
非預定義異常:
??????
沒名字的系統異常,可以用
pragma exception_int
給它關聯一個名字。
自定義異常:
??????
需要用
RAISE
或
RAISE_APPLICATION_ERROR
生成的異常。
?
下面是一些要用到的屬于
;
Exception section
(異常處理模塊)
它是
pl/sql
語句塊種包含一個或多個異常句柄的部分。
Exception section
的結構基本上與
case
相似。
Raise
(產生)
通過通知
pl/sql runtime
引擎有錯誤來中止當前程序的運行。也可通過顯式的請求,如:
RAISE
或
RAISE_APPLICATION_ERROR
來
RAISE
一個異常。
Handle
(句柄,某一個異常處理的代碼)
在
exception section
中捕捉錯誤。可以在
handle
中編寫程序來處理異常,比如將錯誤記入
log
中,顯示一個錯誤信息,將異常傳出當前程序快。
Scope
(作用范圍
)
??????
一個異常從產生、被捕捉到處理整個過程所處的程序部分。
Propagation
(傳遞)
如果一個異常沒有被處理,那么它將被傳遞到但前塊的上一級,它有可能是另一個代碼快,也可能是系統。
Unhandled exception
(未被處理的異常)
如果一個異常沒有被處理,并一直被傳遞道理系統中,那么它被稱為
unhandled exception
。
Un-named or anonymous excepttion
(匿名異常)
??????
(在異常類型中有介紹)
Named exception
(命名異常)
??????
包括系統異常中有名字的那部分和用戶定義的名字。