在程式執行期間,可能會發生任何數量的錯誤(在 PL/SQL 中稱為異常)。當引發異常時,程式的正常執行會停止,並且程式的控制權會轉移到程式的錯誤處理部分。異常可能是伺服器產生的預定義錯誤,也可能是引發使用者定義的異常的邏輯錯誤。
使用者定義的異常從不由伺服器引發;它們由 RAISE 語句顯式引發。當開發人員定義的邏輯規則被破壞時,將引發使用者定義的異常;邏輯規則被破壞的一個常見例子發生在對資金不足的賬戶出具支票時。嘗試對資金不足的賬戶兌現支票時,將引發使用者定義的異常。
您可以在函數、預存程序、包或匿名塊中定義異常。雖然不能在同一個塊中兩次聲明同一個異常,但可以在兩個不同的塊中聲明同一個異常。
在實現使用者定義的異常之前,必須在函數、預存程序、包或匿名塊的聲明部分中聲明該異常。這樣,即可使用 RAISE 語句引發該異常:
DECLARE
exception_name EXCEPTION;
BEGIN
...
RAISE exception_name;
...
END;exception_name 是該異常的名稱。
未處理的異常通過呼叫堆疊傳播回去。如果該異常仍然未處理,則最終將會報告給用戶端應用程式。
在塊中聲明的使用者定義的異常被視為該塊的本地異常,並且是該塊內的任何嵌套塊的全域異常。要引用位於外部塊中的異常,必須為外部塊分配一個標籤;然後以塊名稱作為異常名稱的首碼:
block_name.exception_name相反的是,外部塊不能引用嵌套塊中聲明的異常。
聲明的範圍僅限於在其中聲明該異常的塊。除非該異常是在包中建立的,並且在引用時由包名稱限定。例如,要引發一個名為 Out_of_stock 的異常(位於名為 Inventory_control 的包中),程式必須引發具有以下名稱的錯誤:
inventory_control.out_of_stock以下樣本示範了如何在包中聲明使用者定義的異常。當在 check_balance 中引發時,使用者定義的異常不需要包限定符,因為它與異常位於同一包中:
CREATE OR REPLACE PACKAGE ar AS
overdrawn EXCEPTION;
PROCEDURE check_balance(p_balance NUMBER, p_amount NUMBER);
END;
CREATE OR REPLACE PACKAGE BODY ar AS
PROCEDURE check_balance(p_balance NUMBER, p_amount NUMBER)
IS
BEGIN
IF (p_amount > p_balance) THEN
RAISE overdrawn;
END IF;
END;以下預存程序 (purchase) 調用 check_balance 預存程序。如果 p_amount 大於 p_balance,則 check_balance 會引發異常;purchase 會捕獲 ar.overdrawn 異常。purchase 必須使用包限定名稱 (ar.overdrawn) 來引用異常,因為 purchase 未在 ar 包中定義。
CREATE PROCEDURE purchase(customerID INT, amount NUMERIC)
AS
BEGIN
ar.check_ balance(getcustomerbalance(customerid), amount);
record_purchase(customerid, amount);
EXCEPTION
WHEN ar.overdrawn THEN
raise_credit_limit(customerid, amount*1.5);
END;當 ar.check_balance 引發異常時,執行會跳到 purchase 中定義的例外處理常式:
EXCEPTION
WHEN ar.overdrawn THEN
raise_credit_limit(customerid, amount*1.5);該例外處理常式會提高客戶的信用額度,然後結束。當例外處理常式結束時,執行會從 ar.check_balance 後面的語句恢複。