PL/SQL(Procedural Language/SQL)是 Oracle 的程序化擴展語言,包含完整的資料類型、條件結構、迴圈結構與異常處理結構。它可執行 SQL 語句,SQL 中亦可呼叫 PL/SQL 函數,實現緊密整合。
DECLARE
-- 宣告區:變數、游標、自訂異常等
BEGIN
-- 執行區:業務邏輯、SQL 操作
EXCEPTION
-- 異常處理區:捕獲並處理錯誤
END;
Oracle 內建的常見錯誤,如:
NO_DATA_FOUND - 查詢無資料TOO_MANY_ROWS - 單列查詢回傳多列ZERO_DIVIDE - 除以零DUP_VAL_ON_INDEX - 唯一索引違規INVALID_CURSOR - 非法游標操作Oracle 錯誤碼但無預定義名稱,需使用 PRAGMA EXCEPTION_INIT 綁定:
DECLARE
e_custom_error EXCEPTION;
PRAGMA EXCEPTION_INIT(e_custom_error, -20001);
BEGIN
RAISE e_custom_error;
EXCEPTION
WHEN e_custom_error THEN
DBMS_OUTPUT.PUT_LINE('自訂錯誤被捕獲');
END;
完全由開發者定義的業務異常:
DECLARE
e_insufficient_funds EXCEPTION;
v_balance NUMBER := 100;
v_withdraw NUMBER := 200;
BEGIN
IF v_withdraw > v_balance THEN
RAISE e_insufficient_funds;
END IF;
EXCEPTION
WHEN e_insufficient_funds THEN
DBMS_OUTPUT.PUT_LINE('餘額不足,無法提款');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('其他錯誤:' || SQLERRM);
END;
-- 推薦:精確捕獲
EXCEPTION
WHEN NO_DATA_FOUND THEN
-- 處理無資料情況
WHEN DUP_VAL_ON_INDEX THEN
-- 處理重複鍵值
WHEN OTHERS THEN
-- 記錄未預期錯誤
LOG_ERROR(SQLCODE, SQLERRM);
RAISE; -- 重新拋出或轉換
SQLCODE - 回傳錯誤代碼(負數)SQLERRM - 回傳錯誤訊息文字若內層區塊未處理異常,會向外層傳播。可使用 RAISE 重新拋出,或 RAISE_APPLICATION_ERROR 轉換為應用層錯誤:
RAISE_APPLICATION_ERROR(-20001, '業務邏輯錯誤:' || SQLERRM);
CREATE TABLE error_log (
error_time TIMESTAMP DEFAULT SYSTIMESTAMP,
error_code NUMBER,
error_msg VARCHAR2(4000),
call_stack VARCHAR2(4000)
);
-- 在 EXCEPTION 區塊中
INSERT INTO error_log (error_code, error_msg, call_stack)
VALUES (SQLCODE, SQLERRM, DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
SAVEPOINT before_update;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
EXCEPTION
WHEN e_insufficient_funds THEN
ROLLBACK TO before_update;
-- 繼續其他邏輯
PL/SQL 異常處理機制強大且靈活,核心在於:預測可能錯誤、精確捕獲特定異常、記錄完整錯誤上下文、適當轉換或重新拋出。良好的異常處理能顯著提升系統健壯性與可維護性。