首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> Oracle 資料庫 >> Oracle 資料庫基礎

Oracle 異常處理完整教學:預定義/自定義異常、RAISE/RAISE_APPLICATION_ERROR、異常傳遞機制

     編輯:Oracle 資料庫基礎

PL/SQL 區塊結構與異常區

DECLARE
  -- 宣告區
BEGIN
  -- 執行區
EXCEPTION
  -- 異常處理區(每個區塊僅一個)
  WHEN exception_name THEN ...
  WHEN OTHERS THEN ...
END;

兩大異常來源

類別代表處理方式
Oracle 預定義異常NO_DATA_FOUND、TOO_MANY_ROWS、ZERO_DIVIDE、DUP_VAL_ON_INDEX、VALUE_ERROR...直接 WHEN name THEN 捕捉
使用者自定義異常業務邏輯錯誤(如餘額不足、狀態不允許操作)宣告 e_my_exc EXCEPTION; + PRAGMA EXCEPTION_INIT(e_my_exc, -20001);

常見預定義異常速查

三種觸發異常方式

  1. Oracle 自動拋出: 違反約束、型別錯誤等。
  2. RAISE 手動拋出: RAISE e_my_exc; 或 RAISE NO_DATA_FOUND;
  3. RAISE_APPLICATION_ERROR: 攜帶自訂錯誤訊息(-20000 ~ -20999)。
    RAISE_APPLICATION_ERROR(-20001, '餘額不足,無法扣款');

異常傳遞機制

巢狀區塊:子區塊未處理的異常**自動向外傳遞**至父區塊的 EXCEPTION 區;父區塊亦無處理則繼續向外,直到最外層或無人處理則回報給呼叫端(Client/JDBC/OCI)。

BEGIN
  BEGIN
    v := 1/0;  -- 子區塊拋 ZERO_DIVIDE
    EXCEPTION WHEN OTHERS THEN NULL;  -- 子區塊吞掉,不傳遞
  END;
EXCEPTION WHEN ZERO_DIVIDE THEN ...  -- 父區塊捕捉不到,因子區塊已處理(雖為 NULL)
END;

**最佳實踐:子區塊僅處理能真正恢復的異常,其餘拋給父區塊統一記錄/轉換。**

實戰範例:業務異常統一轉碼

DECLARE
  e_insuff_fund EXCEPTION;
  PRAGMA EXCEPTION_INIT(e_insuff_fund, -20001);
BEGIN
  IF balance < amount THEN
    RAISE_APPLICATION_ERROR(-20001, '帳戶 '||acc_id||' 餘額 '||balance||' 不足扣除 '||amount);
  END IF;
  -- 扣款邏輯
EXCEPTION
  WHEN e_insuff_fund THEN
    LOG_ERROR(SQLCODE, SQLERRM);
    RAISE;  -- 重新拋出讓上層決定回滾/重試
  WHEN OTHERS THEN
    LOG_ERROR(SQLCODE, SQLERRM);
    RAISE_APPLICATION_ERROR(-20999, '系統錯誤:'||SQLERRM);
END;

總結

異常處理 = 程式健壯性的最後防線。核心口訣:**預定義異常直接 WHEN、自定義異常 PRAGMA 綁錯誤碼、RAISE_APPLICATION_ERROR 傳遞業務語意、子區塊不吞無法恢復的異常、WHEN OTHERS 最後兜底並記錄 SQLCODE/SQLERRM**。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
異常名稱錯誤碼觸發情境
NO_DATA_FOUND+100 / -1403SELECT INTO 0 行
TOO_MANY_ROWS-1422SELECT INTO >1 行
ZERO_DIVIDE-1476除以 0
DUP_VAL_ON_INDEX-1唯一鍵衝突
VALUE_ERROR-6502字串截斷/型別轉換失敗
INVALID_NUMBER-1722SQL 中字串轉數字失敗
CURSOR_ALREADY_OPEN-6511重複 OPEN 游標