存儲過程是 DB2 伺服器端邏輯的核心載體,能將多條 SQL 封裝為單次網路調用、隔離資料邏輯與應用邏輯、返回多結果集。本文建立「概念→特性→SQL PL 語法→實戰範本」完整知識鏈,助力開發者快速掌握高效、安全的 SQL Procedure 開發。
| 模式 | 方向 | 說明 |
|---|---|---|
| IN | 調用者 → SP | 輸入值,SP 內可讀不可回寫 |
| OUT | SP → 調用者 | 輸出值,SP 內初始為 NULL,須賦值 |
| INOUT | 雙向 | 傳入值可被 SP 修改並回傳 |
結果集返回步驟(SQL SP 專用):
需在 `CREATE PROCEDURE` 宣告 `DYNAMIC RESULT SETS n`(`n` ≥ 實際返回集數),否則超集觸發 `SQLCODE +464` 警告。
DECLARE v_salary DECIMAL(9,2) DEFAULT 0;
DECLARE v_dept CHAR(3);
DECLARE my_condition CONDITION FOR SQLSTATE '23505'; -- 自定義異常名
SET v_sal = (SELECT SALARY FROM EMP WHERE EMPNO = '000010'); -- 子查詢單值
SET v_sal = NULL;
SET v_sal = DEFAULT;
SET v_user = USER, v_today = CURRENT DATE; -- 多變量並行
SET (v_pay, v_bonus) = (SELECT SALARY, BONUS FROM EMP WHERE EMPNO = '000010');
-- IF 三種形態
IF v_sal BETWEEN 10000 AND 90000 THEN ... END IF;
IF v_dept IN ('A00','B01') THEN ... ELSE ... END IF;
IF EXISTS (SELECT 1 FROM EMP) THEN ... ELSEIF ... END IF;
-- WHILE 迴圈(可選 LABEL)
lbl: WHILE v_cnt < 10 DO
SET v_cnt = v_cnt + 1;
IF v_cnt = 5 THEN ITERATE lbl; END IF; -- 回到 WHILE 頭
IF v_cnt = 8 THEN LEAVE lbl; END IF; -- 跳出迴圈
END WHILE lbl;
-- FOR 遊標迴圈(隱式 OPEN/FETCH/CLOSE)
FOR r_emp AS SELECT * FROM EMP WHERE BONUS > 1000 DO
SET v_total_bonus = v_total_bonus + r_emp.BONUS;
END FOR;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS v_err_msg = MESSAGE_TEXT;
SIGNAL SQLSTATE '75001' SET MESSAGE_TEXT = 'SP Error: ' || v_err_msg;
END;
GET DIAGNOSTICS v_rows = ROW_COUNT; -- 取得前一條 INSERT/UPDATE/DELETE 影響行數
CREATE OR REPLACE PROCEDURE SP_EMP_BONUS_STAT (
IN p_dept CHAR(3),
OUT p_total DECIMAL(15,2),
OUT p_cnt INT
) DYNAMIC RESULT SETS 1
LANGUAGE SQL
SPECIFIC SP_EMP_BONUS_STAT
BEGIN
DECLARE v_sqlstate CHAR(5) DEFAULT '00000';
DECLARE v_msg VARCHAR(32000);
DECLARE c_emp CURSOR WITH RETURN TO CALLER FOR
SELECT EMPNO, LASTNAME, BONUS FROM EMP WHERE WORKDEPT = p_dept AND BONUS > 0;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1 v_sqlstate = RETURNED_SQLSTATE, v_msg = MESSAGE_TEXT;
SIGNAL SQLSTATE '75002' SET MESSAGE_TEXT = 'SP_EMP_BONUS_STAT failed: ' || v_msg;
END;
OPEN c_emp;
SELECT SUM(BONUS), COUNT(*) INTO p_total, p_cnt
FROM EMP WHERE WORKDEPT = p_dept AND BONUS > 0;
-- 不 CLOSE c_emp,直接返回結果集
END @

結語:SQL Procedure 以「純 SQL 實現伺服器邏輯」實現了開發效率與執行效能的雙贏。掌握 `DECLARE/SET/IF/WHILE/FOR/ITERATE/LEAVE/SIGNAL/GET DIAGNOSTICS` 九大核心語句,配合「集合優先、參數化動態 SQL、原子性邊界清晰」三大原則,即可構建健壯、可維護、高效能的資料庫端服務層。