pl/sql
提供了強(qiáng)大而靈活的手段來捕捉和處理程序產(chǎn)生的異常,從而使
oracle
的用戶遠(yuǎn)離一些令人煩惱的
bug
。
?
pl/sql
異常處理的概念和術(shù)語
?
在
oracle
中所有的錯(cuò)誤都被認(rèn)為是不應(yīng)該發(fā)生的異常。一個(gè)異常可能是以下
3
種情況的一種:
u??????
由系統(tǒng)產(chǎn)生的錯(cuò)誤(“
out of memory
”或“
duplicate value in index
”)
u??????
用戶行為導(dǎo)致的錯(cuò)誤
u??????
應(yīng)用程序給用戶的一個(gè)警告
pl/sql
用一種異常句柄的結(jié)構(gòu)來捕捉和響應(yīng)錯(cuò)誤。正是有了異常句柄的存在,我們能很方便的分離異常處理代碼與可執(zhí)行代碼。與線性的代碼相比,為了處理異常,異常句柄提供了一種類似事件驅(qū)動(dòng)的模式;換句話說,就是不管一種特定的錯(cuò)誤在何時(shí)何地發(fā)生,它都將被同一個(gè)代碼處理。
當(dāng)一個(gè)錯(cuò)誤出現(xiàn)后,無論它是系統(tǒng)還是程序產(chǎn)生的,都將導(dǎo)致一個(gè)異常。之后,可執(zhí)行程序被中斷,控制權(quán)轉(zhuǎn)移給異常處理代碼。處理完異常后,程序?qū)⒉粫?huì)回到先前被中斷的位置,相反的,控制權(quán)被交給了當(dāng)前程序的外圍模塊(可能是程序,也可能是系統(tǒng))。
?????? 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;
因?yàn)?/span>
old_value
是一個(gè)未被定義的變量,所以將產(chǎn)生一個(gè)錯(cuò)誤,并將給異常處理模塊處理。
?
從異常的可應(yīng)用范圍出發(fā),可將異常分為兩類:
系統(tǒng)異常:
由
oracle
定義并由
pl/sql runtime
引擎在檢測到錯(cuò)誤時(shí)產(chǎn)生的異常。一些系統(tǒng)異常有名字,比如
NO_DATA_FOUND
,然而大多數(shù)的異常僅僅只有數(shù)字編號和描述。這些異常無論在哪個(gè)
pl/sql
中程序都能被應(yīng)用。
共有
21
個(gè)命名的系統(tǒng)異常:
命名的系統(tǒng)異常
|
產(chǎn)生原因
|
ACCESS_INTO_NULL
|
未定義對象
|
CASE_NOT_FOUND
|
CASE
中若未包含相應(yīng)的
WHEN
,并且沒有設(shè)置
ELSE
時(shí)
|
COLLECTION_IS_NULL
|
集合元素未初始化
|
CURSER_ALREADY_OPEN
|
游標(biāo)已經(jīng)打開
|
DUP_VAL_ON_INDEX
|
唯一索引對應(yīng)的列上有重復(fù)的值
|
INVALID_CURSOR
|
在不合法的游標(biāo)上進(jìn)行操作
|
INVALID_NUMBER
|
內(nèi)嵌的
sql
語句不能將字符轉(zhuǎn)換為數(shù)字
|
NO_DATA_FOUND
|
使用
select into
未返回行,或應(yīng)用索引表未初始化的元素時(shí)
|
TOO_MANY_ROWS
|
執(zhí)行
select iotn
時(shí),返回超過一行
|
ZERO_DIVIDE
|
除數(shù)為
0
|
SUBSCRIPT_BEYOND_COUNT
|
元素下標(biāo)超過嵌套表或
VARRAY
的最大值
|
SUBSCRIPT_OUTSIDE_LIMIT
|
使用嵌套表或
VARRAY
時(shí),將下標(biāo)指定為負(fù)數(shù)
|
VALUE_ERROR
|
賦值時(shí),變量長度不足以容納實(shí)際數(shù)據(jù)
|
LOGIN_DENIED
|
Pl/sql
應(yīng)用程序連接到
oracle
數(shù)據(jù)庫時(shí),提供了不正確的用戶名或密碼
|
NOT_LOGGED_ON
|
Pl/sql
應(yīng)用程序在沒有連接
oralce
數(shù)據(jù)庫的情況下訪問數(shù)據(jù)
|
PROGRAM_ERROR
|
Pl/sql
內(nèi)部問題,可能需要重裝數(shù)據(jù)字典&
pl./sql
系統(tǒng)包
|
ROWTYPE_MISMATCH
|
宿主游標(biāo)變量與
pl/sql
游標(biāo)變量的返回類型不兼容
|
SELF_IS_NULL
|
使用對象類型時(shí),在
null
對象上調(diào)用對象方法
|
STORAGE_ERROR
|
運(yùn)行
pl/sql
時(shí),超出內(nèi)存空間
|
SYS_INVALID_ID
|
無效的
ROWID
字符串
|
TIMEOUT_ON_RESOURCE
|
Oracle
在等待資源時(shí)超時(shí)
|
?
由程序員定義的異常:
程序員在程序中定義的異常,它只是在特定的程序種有效。可以使用
EXCEPTION_INT
這個(gè)
pragma
將一個(gè)無名字的系統(tǒng)異常與一個(gè)程序員定義的名字相關(guān)聯(lián)。或者用
RAISE_APPLICATION_ERROE
來自己定義一個(gè)異常的數(shù)字編號和描述。
?
按異常生成方式可分為:
預(yù)定義異常:
??????
就是上面表中的
21
種有名字的系統(tǒng)異常。
非預(yù)定義異常:
??????
沒名字的系統(tǒng)異常,可以用
pragma exception_int
給它關(guān)聯(lián)一個(gè)名字。
自定義異常:
??????
需要用
RAISE
或
RAISE_APPLICATION_ERROR
生成的異常。
?
下面是一些要用到的屬于
;
Exception section
(異常處理模塊)
它是
pl/sql
語句塊種包含一個(gè)或多個(gè)異常句柄的部分。
Exception section
的結(jié)構(gòu)基本上與
case
相似。
Raise
(產(chǎn)生)
通過通知
pl/sql runtime
引擎有錯(cuò)誤來中止當(dāng)前程序的運(yùn)行。也可通過顯式的請求,如:
RAISE
或
RAISE_APPLICATION_ERROR
來
RAISE
一個(gè)異常。
Handle
(句柄,某一個(gè)異常處理的代碼)
在
exception section
中捕捉錯(cuò)誤。可以在
handle
中編寫程序來處理異常,比如將錯(cuò)誤記入
log
中,顯示一個(gè)錯(cuò)誤信息,將異常傳出當(dāng)前程序快。
Scope
(作用范圍
)
??????
一個(gè)異常從產(chǎn)生、被捕捉到處理整個(gè)過程所處的程序部分。
Propagation
(傳遞)
如果一個(gè)異常沒有被處理,那么它將被傳遞到但前塊的上一級,它有可能是另一個(gè)代碼快,也可能是系統(tǒng)。
Unhandled exception
(未被處理的異常)
如果一個(gè)異常沒有被處理,并一直被傳遞道理系統(tǒng)中,那么它被稱為
unhandled exception
。
Un-named or anonymous excepttion
(匿名異常)
??????
(在異常類型中有介紹)
Named exception
(命名異常)
??????
包括系統(tǒng)異常中有名字的那部分和用戶定義的名字。