PL/SQL 例外處理分為系統預定義 (如 NO_DATA_FOUND) 與使用者自訂。善用自訂例外可實現業務規則驗證失敗時的優雅跳出與統一錯誤碼回傳。
CREATE OR REPLACE PROCEDURE gen_payroll(p_center_id NUMBER,
p_retcode OUT VARCHAR2,
p_retinfo OUT VARCHAR2) IS
-- 1. 宣告自訂例外
biz_exception EXCEPTION;
PRAGMA EXCEPTION_INIT(biz_exception, -20001); -- 可選:指定錯誤碼
BEGIN
-- 2. 業務檢查失敗時主動 RAISE
IF payroll_exists(p_center_id) THEN
p_retcode := '-1';
p_retinfo := '薪資單已存在,請勿重複產生。';
RAISE biz_exception; -- 跳出至 EXCEPTION 區塊
END IF;
-- 正常業務邏輯
INSERT INTO payroll ...;
COMMIT;
p_retcode := '0';
p_retinfo := 'SUCCESS';
EXCEPTION
-- 3. 捕捉自訂例外:只記錄/回傳,不 ROLLBACK (視需求)
WHEN biz_exception THEN
NULL; -- 已在上方設定 retcode/retinfo
-- 4. 捕捉所有其他例外:統一記錄、回滾
WHEN OTHERS THEN
p_retcode := SQLCODE;
p_retinfo := SUBSTR(SQLERRM, 1, 1000);
DBMS_OUTPUT.PUT_LINE('SYS ERROR ' || p_retcode || ': ' || p_retinfo);
ROLLBACK;
END gen_payroll;
/
```
預定義例外常見清單
例外名稱 錯誤碼 觸發情境
NO_DATA_FOUND+100 SELECT INTO 查無資料
TOO_MANY_ROWS-1422 SELECT INTO 回傳多行
DUP_VAL_ON_INDEX-0001 唯一索引/主鍵衝突
VALUE_ERROR-06502 型別轉換/長度溢位
INVALID_CURSOR-1001 游標操作非法
進階技巧
- 錯誤碼標準化:自訂例外建議使用
-20000 ~ -20999 區間,配合 PRAGMA EXCEPTION_INIT 固定錯誤碼,方便前端對照錯誤訊息表。
- 例外重拋:
RAISE; (無參數) 在 WHEN OTHERS 中保留原始堆疊追蹤再拋給上層。
- 批次處理部分失敗:搭配
FORALL ... SAVE EXCEPTIONS 與 SQL%BULK_EXCEPTIONS 處理。
避坑原則
- 永遠在
WHEN OTHERS 最後才捕捉,避免吞沒預期例外。
- 自訂例外不要在
WHEN OTHERS 前被捕捉 (順序錯誤)。
- 生產環境禁止只寫
WHEN OTHERS THEN NULL; 吞錯誤。
規範化例外處理模式,讓 PL/SQL 程式健壯、可追蹤、易維護。