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

DB2 SQL PL 核心語法精要:從結果集回傳到控制流、異常處理的開發速查手冊

     編輯:DB2 教學

承接上篇語法導航,本文聚焦 SQL PL (SQL Procedural Language) 實戰開發核心:如何回傳結果集、控制流程語句、變數宣告與賦值、條件/迴圈/游標/異常處理完整語法與範例。適合作為寫 Procedure/Function/Trigger 時的桌邊速查卡。

結果集回傳三步曲(核心模式)

  1. 宣告游標:`DECLARE cursor_name CURSOR WITH RETURN TO CALLER FOR select-statement;`
  2. 開啟游標:`OPEN cursor_name;`
  3. 不關閉直接結束程序:引擎自動將開啟的 `WITH RETURN` 游標封裝為結果集回傳呼叫端。

DECLARE clientCur CURSOR WITH RETURN TO CALLER FOR SELECT * FROM staff;
OPEN clientCur;
-- 此處不寫 CLOSE clientCur

SQL PL 程式結構基礎

  • 適用範圍:Procedure、Function、Trigger、動態複合語句(單次呼叫的 SQL 區塊)。
  • 核心能力:控制邏輯流、宣告/設定變數、處理警告與異常。
  • 不可執行:`CREATE/DROP TABLE | INDEX | VIEW`(DDL 需用動態 SQL `EXECUTE IMMEDIATE`)。
  • 區塊結構:`BEGIN [ATOMIC] ... END`。`ATOMIC` 表示整個區塊為單一交易,失敗全捲回。

變數宣告與賦值

宣告語法


-- 一般變數
DECLARE sql-var-name data-type [DEFAULT default-value];

-- 條件/異常名稱(對應 SQLSTATE)
DECLARE condition-name CONDITION FOR SQLSTATE 'value';

賦值語法


-- 純量子查詢(必須只回傳 1 行 1 欄)
SET var = (SELECT salary FROM employee WHERE empno = 5);

-- 直接給值
SET var = 10000;
SET var = NULL;
SET var = DEFAULT;  -- 使用宣告時的 DEFAULT 值

-- 特殊暫存器
SET userid = USER;
SET today = CURRENT DATE;

-- 多變數同時賦值
SET pay = 10000, bonus = 1500;
SET (pay, bonus) = (10000, 1500);
SET (pay, bonus) = (SELECT pay, bonus FROM employee WHERE empno = 5);

控制流程語句完整速查

條件判斷:IF 三種形式


-- 1. 簡單 IF
IF (salary BETWEEN 10000 AND 90000) THEN
    -- statements
END IF;

-- 2. IF-ELSE
IF (deptno IN ('A00','B01')) THEN
    -- statements
ELSE
    -- statements
END IF;

-- 3. IF-ELSEIF-ELSE
IF (EXISTS (SELECT * FROM employee)) THEN
    -- statements
ELSEIF (SELECT COUNT(*) FROM employee) > 0 THEN
    -- statements
ELSE
    -- statements
END IF;

亮點:條件式中可直接使用 SQL 運算子(`BETWEEN`、`IN`、`EXISTS`、子查詢比較)。

迴圈:WHILE 與 FOR


-- WHILE 迴圈(可選標籤)
label_loop: WHILE condition DO
    -- SQL PL statements
END WHILE label_loop;

-- FOR 迴圈:專為遍歷查詢結果集設計(隱含游標)
label_for: FOR row_name AS SELECT statement DO
    -- 直接用 row_name.col_name 存取欄位
    SET total_bonus = total_bonus + row_name.bonus;
END FOR label_for;

FOR 迴圈範例:


FOR emp AS SELECT * FROM employee WHERE bonus > 1000 DO
    SET total_bonus = total_bonus + emp.bonus;
END FOR;

流程控制:ITERATE / LEAVE

  • ITERATE label:跳回標籤對應迴圈開頭(類似 `continue`)。
  • LEAVE label:跳離標籤對應迴圈/區塊(類似 `break`)。

check_bonus: FOR emp AS SELECT * FROM employee DO
    IF emp.bonus > 10000 THEN
        SET total_bonus = total_bonus + emp.bonus;
    ELSE
        ITERATE check_bonus;  -- 跳過本輪剩餘邏輯,直接下一筆
    END IF;
END FOR check_bonus;

異常處理:SIGNAL / CONDITION / HANDLER


-- 自訂 SQLSTATE(建議 7,8,9 或 I-Z 開頭)
SIGNAL SQLSTATE '75001' SET MESSAGE_TEXT = '薪資超出合理範圍';

-- 使用預先宣告的 CONDITION
DECLARE invalid_salary CONDITION FOR SQLSTATE '75001';
SIGNAL invalid_salary SET MESSAGE_TEXT = '薪資超出合理範圍';

-- 區塊級異常處理器
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
    -- 記錄錯誤、設定輸出參數預設值
    SET out_err_code = SQLCODE;
    SET out_err_msg  = '程序內部錯誤';
END;

DECLARE CONTINUE HANDLER FOR NOT FOUND
    SET medianSalary = 6666;  -- 找不到資料給預設值

診斷資訊:GET DIAGNOSTICS

僅限 SQL PL 觸發器或複合語句(非 Function)使用,取得前一條 `INSERT/UPDATE/DELETE` 影響列數。


GET DIAGNOSTICS v_rowcount = ROW_COUNT;

完整實戰範例:帶異常處理的員工獎金統計 Procedure


CREATE PROCEDURE CALC_DEPT_BONUS
(
    IN  p_deptno   CHAR(3),
    OUT p_total    DECIMAL(15,2),
    OUT p_cnt      INTEGER,
    OUT p_err_code INTEGER,
    OUT p_err_msg  VARCHAR(200)
)
LANGUAGE SQL
MODIFIES SQL DATA
NO EXTERNAL ACTION
BEGIN
    DECLARE v_bonus   DECIMAL(15,2);
    DECLARE v_sqlcode INTEGER DEFAULT 0;
    
    -- 異常處理器
    DECLARE EXIT HANDLER FOR SQLEXCEPTION
    BEGIN
        GET DIAGNOSTICS CONDITION 1
            v_sqlcode = DB2_RETURNED_SQLCODE,
            p_err_msg = MESSAGE_TEXT;
        SET p_err_code = v_sqlcode;
        SET p_total = 0;
        SET p_cnt = 0;
    END;
    
    SET p_total = 0;
    SET p_cnt = 0;
    
    FOR emp AS
        SELECT bonus FROM employee WHERE workdept = p_deptno AND bonus IS NOT NULL
    DO
        SET p_total = p_total + emp.bonus;
        SET p_cnt = p_cnt + 1;
    END FOR;
    
    SET p_err_code = 0;
    SET p_err_msg = 'SUCCESS';
END

開發者速查卡(列印備用)

任務關鍵語法注意事項
回傳結果集DECLARE ... CURSOR WITH RETURN TO CALLER / OPEN / 不 CLOSEDYNAMIC RESULT SETS >= 1
宣告變數DECLARE v_name TYPE DEFAULT val;支援所有 SQL 型別,含 ROW/ARRAY (新版)
賦值SET v = (SELECT ...); / SET (a,b) = ...子查詢必須單列單行
條件判斷IF ... THEN ... [ELSEIF ...] [ELSE ...] END IF條件可含 SQL 運算子/子查詢
遍歷查詢結果FOR row AS SELECT ... DO ... END FOR最簡潔,隱含游標管理
條件迴圈WHILE cond DO ... END WHILE需自行管理游標或計數器
跳過本輪ITERATE label需在 FOR/WHILE 區塊內
跳出迴圈LEAVE label需標籤
拋出自訂錯誤SIGNAL SQLSTATE '...' SET MESSAGE_TEXT = '...'SQLSTATE 7,8,9,I-Z 開頭
捕捉異常DECLARE EXIT/CONTINUE HANDLER FOR SQLEXCEPTION/SQLSTATE/CONDITIONEXIT=離開區塊, CONTINUE=繼續下一句
取得影響列數GET DIAGNOSTICS v = ROW_COUNT僅限 Trigger/複合語句

核心心法:SQL PL = SQL 的語意表達力 + 程式語言的控制流。掌握 FOR 迴圈遍歷結果集、HANDLER 統一異常處理、WITH RETURN 回傳結果集三大核心模式,即可應付 95% 預存程序/觸發器開發場景。把這張速查卡貼在螢幕邊,寫 Code 時查閱,效率倍增。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved