PL SQL異常處理

2021-09-20 22:45:33 字數 3834 閱讀 1390

異常處理語句塊結構

異常處理結構示例

declare

begin

exception

end;

對於未處理的異常,可以通過when others then來提供乙個統一的異常處理

declare

begin

exception

end;

預定義異常使用示例

declare

begin

exception

end;

自定義異常

declare

begin

end;

異常是一種錯誤的表現形式,而不是乙個真正的變數,因此不能再賦值語句或sql語句中使用異常,但是異常和變數的作用範圍和規則是相同的。

作用域範圍

自定義異常和變數的作用域和規則相同。

1.在同乙個塊中不能宣告乙個異常超過兩次,但是可以再不同的塊中宣告相同的異常。但是可以再不同的塊中宣告兩個相同的異常。

2.內層塊定義的異常不可以被外層使用,內層可以呼叫外層定義的異常

3.如果在子塊重新宣告外部塊中同名的異常,將覆蓋外部塊中的全域性異常,使得子塊不能引用外部塊中的全域性異常,但是可以再在標籤塊中宣告相同的異常

使用exception_init

如果一些異常並沒有異常名稱,此時在when子句中無法使用具體的異常名稱,必須要使用others異常處理器進行捕捉,通過exception_init編譯指示,可以為這些不在預定義異常範圍之類的異常新增名稱。

編譯指示是指能在編譯期而非執行時進行處理的編譯指令

編譯指令exception_init將告訴編譯器,將異常名稱和錯誤編號關聯起來,使得在plsql語句塊中可以使用名稱來引用所有的內部異常。

declare

begin

exception

end;

declare or replace procedure registeremployee ()as

begin

exception

end;

輸出  begin

end;

ora-20003:插入資料時出現錯誤!異常編碼:-20002異常描述ora-20002;

丟擲異常

使用raise語句丟擲異常示例

declare

begin

exception

end;

處理異常

可以使用or關鍵字進行分隔即可。

declare

begin

exception

end;

使用sqlcode和sqlerrm

儘管乙個異常在同一時刻只能丟擲一次,但是實際上錯誤的訊息文字可能包含來自多個異常的訊息這是因為異常具有傳遞特性。

sqlcode函式返回當前的錯誤編碼。

sqlerrm函式返回訊息文字

declare

begin

exception

end;

sqlerrm函式還可以接受乙個負數的單精度引數,它將返回與該數字相關的文字,否則將返回當前異常的錯誤訊息。

想返回no_data_found的錯誤訊息,可以傳遞錯誤訊息號100

異常的傳遞

異常的傳遞是指當異常被丟擲時,執行立即跳轉到exception語句塊中的異常處理器,異常處理器中查詢是否匹配的異常,如果在當前的pl/sql塊或子程式中沒有找到對應的異常處理器,那麼這個異常會向其plsql塊的外層或子程式的呼叫方傳遞,直到沒有可以搜尋到的塊為止,這裡plsql會向plsql引擎丟擲乙個未處理的異常。

執行時異常傳遞

例如declare

begin

exception

end;

1.首先搜尋內層塊的異常處理區中的異常,在本地塊中的e_innerexception異常具有乙個異常處理器,因此該異常將在本地塊中被處理

2.其他的兩個異常將向外傳遞,傳送給外層pl/sql塊的異常處理區,在外層的異常處理區中具有乙個e_outerexception的異常處理器,因此該異常將在外層塊中**捉並處理

3.異常e_threeexception並沒有任何處理器,該異常將被傳遞到呼叫環境,由呼叫環境進行處理。比如sql*plus會彈出乙個異常。

宣告時異常傳遞

示例begin

exception

end;

在宣告乙個變數v_ename,並賦予了初始值abc,這個賦值產生了ora-06502異常,因為varchar2(2)不能包含abc這3個字元。儘管在子塊的exception區具有when others then 異常處理語句,但是宣告區中丟擲的異常並不會被本地塊所捕獲,而是向外層傳遞,被外層的異常處理區中的others異常處理器捕獲,因此最終可以看到如下所示:

錯誤編號:-6502 錯誤訊息:ora-06502:pl/sql:數字或值錯誤:字串緩衝區太小。

異常處理器中的異常

declare

begin

exception

end;

在巢狀的內層pl/sql塊中,在執行區觸發了3個異常,在異常處理區中捕獲取e_innerexception異常,在處理該異常的處理器中,使用raise語句又觸發了e_outerexception.可以看到即便在內層塊中包含了e_outerexception的異常處理器,但是異常並不會在記憶體塊中的處理器中**獲,而是跳轉到了外層的異常處理器進行處理。

重新丟擲異常

declare

exception 

end;

當e_nocomm觸發後,會被others異常處理器處理,在該異常處理器中,首先輸出了異常資訊,然後呼叫raise語句將異常重新丟擲。此時由於已經是最外層的語句塊,異常將被傳遞到呼叫環境,因此sqlplus將觸發異常。

可以看到當不為rasie指定任何異常名稱時,程式就會把當前的異常重新丟擲。

這種重新丟擲異常的方式只允許在異常程式中這樣做。

異常處理準則

要實現從異常恢復,可以將異常包裝在其自己的子塊中,在子塊中編寫對應的異常控制程式,這樣一旦在子塊中有錯誤發生,子塊內部的異常處理器就能捕獲並處理異常。當子塊結束時,就可以繼續執行外層塊中的下一條語句,因此如下

declare

begin

exception

end;

可以看到,現在查詢並檢測同名的邏輯被封裝到乙個pl/sql子塊中,在子塊中柏涵了異常處理語句,當異常觸發時,將v_newname更改為另乙個名字,從內層塊中退出後,會繼續執行insert語句,直到pl/sql語句塊終止。

獲取異常丟擲的位置

示例declare

begin

exception

end;

當觸發了no_data_found異常時,如何知道是哪個select語句觸發了異常?

方法一:使用遞增的計數器標識sql語句

declare

begin

exception

end;

方法二:將每乙個select語句定義到乙個子塊中去,這樣就可以知道哪個select語句觸發了異常,當然這種方式將導致出現多個異常訊息,因為沒一條select語句都會被執行。

declare

begin

exception

end;

方法三:可以使用dbms_utility.format_error_backtrace函式來獲取錯誤位置,這個函式是oracle10g以後的版本提供的

declare

begin

exception

end;

在發生錯誤時,oracle會為最近一次生成的異常設定乙個棧,並跟蹤它的傳遞過程。

異常與事務處理

在異常中重複事務執行**

declare

begin

end;

pl sql異常處理

丟擲異常 oracle有三種型別的異常錯誤 1 預定義 predefined 異常 oracle預定義的異常情況大約有24個。對這種異常情況的處理,無需在程式中定義,由oracle自動將其引發。2 非預定義 predefined 異常 即其他標準的oracle錯誤。對這種異常情況的處理,需要使用者在...

PLSQL 異常處理

1.異常塊begin pl sql塊 exception when no data found then 沒有找到資料 響應命令 when too many rows then 返回多行,隱式游標每次只能檢索一行資料 響應命令 when invalid number then 字元向數字轉換失敗 響...

plsql異常處理

1.在plsql 中 形式引數和 where 語句中的引數不能一樣,否則的話就就會出現個中莫名其妙的錯誤。function validate import supplier p task seq in number,任務號 p line num in number,行號 p vendor name ...