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

DB2 9.5 SQL Procedure Developer 認證考試 735 核心筆記(一):SQL PL 基礎語法與錯誤處理

     編輯:DB2 教學

考試系列簡介

本系列共 6 篇教學,涵蓋 SQL Procedural Language (SQL PL) 所有核心結構與技巧,包含變數、條件、處理器宣告、控制流程、迴圈、錯誤處理、部署、結果集回傳、巢狀呼叫、資料共享,以及 DB2 9.5 進階特性(樂觀鎖、階層查詢、宣告式全域暫存表)、開發工具 (IBM Data Studio)。適合已通過 Exam 730 (DB2 9 Family Fundamentals) 的考生準備 Exam 735。

SQL PL 簡介

SQL PL 是 SQL/PSM (Persistent Stored Modules) 標準子集,結合 SQL 資料存取便利性與程式語言流程控制,可開發函數、存儲過程、觸發器,將業務邏輯封裝於資料庫物件提升應用效能。

變數宣告

DECLARE variable-name data-type [DEFAULT NULL | DEFAULT constant];
  • 名稱不可與參數、其他變數、欄名重複。
  • 支援所有 DB2 內建型別(含 XML、BLOB/CLOB 等)。
  • DEFAULT 省略時為 NULL。
  • 9.5 新功能:單一 DECLARE 可宣告多個同型別變數,如 DECLARE v1, v2 INT DEFAULT 0;。

陣列資料型別 (9.5 新增)

需先在資料庫建立型別,再於過程/應用中宣告使用。陣列為暫時值,不可持久化存表。

CREATE TYPE type-name AS element-type ARRAY [max-cardinality];
-- 範例
CREATE TYPE numbers AS INTEGER ARRAY[100];
CREATE TYPE names AS VARCHAR(30) ARRAY[];          -- 無上限
CREATE TYPE myschema.totalcomp AS DECIMAL(12,2) ARRAY[];

-- 過程中使用
CREATE PROCEDURE proc_array_test (OUT mynames names)
BEGIN
  DECLARE v_nums numbers;
  SET v_nums = ARRAY[1,2,3,5,7,11];
  SET mynames[1] = 'MARINA';
  -- 存取元素:array-var[subindex],下標 1..cardinality
END

支援 CARDINALITY(array) 取得元素個數等操作函數。

指派敘述

SET variable = expression | NULL; 適用區域變數、全域變數、陣列元素。其他指派方式:VALUES INTO、SELECT/FETCH INTO。

SET v_sal = 50000;
SET v_total = (SELECT SUM(salary) FROM emp);
SET v_pos = POSSTR('MYTEST','TEST');
SET v_arr[10] = 20;
SET v_arr = ARRAY[1,2,3,4];
VALUES CURRENT DATE INTO v_date;
SELECT hiredate INTO v_hired FROM emp WHERE empno = '000010';

特殊暫存器

DBA 定義的儲存區塊,供應用程式存取。常用:CURRENT DATE、CURRENT TIME、CURRENT TIMESTAMP、CURRENT USER、CURRENT PATH。可加底線引用(如 CURRENT_DATE)。部分暫存器可用 SET 更新(如 SET CURRENT SCHEMA = 'MYSCHEMA')。

游標宣告與結果集回傳

DECLARE cursor-name CURSOR [WITHOUT HOLD | WITH HOLD]
  [WITHOUT RETURN | WITH RETURN [TO CALLER | TO CLIENT]]
  FOR select-statement;
  • WITH HOLD:COMMIT 後游標保持開啟(ROLLBACK 仍關閉)。
  • WITH RETURN TO CALLER:結果集回傳給直接呼叫者(預設)。
  • WITH RETURN TO CLIENT:穿透巢狀過程直接回傳給用戶端應用。

回傳結果集三步驟:
1. CREATE PROCEDURE ... DYNAMIC RESULT SETS n
2. DECLARE cursor ... WITH RETURN ...
3. OPEN cursor 並保持開啟(關閉則無法回傳)。

游標處理流程

  1. 區塊開頭 DECLARE CURSOR
  2. OPEN
  3. FETCH INTO 區域變數(FOR 迴圈除外)
  4. CLOSE(結束時隱式關閉)

條件敘述

IF 敘述

IF condition THEN ... 
[ELSEIF condition THEN ...] 
[ELSE ...] 
END IF;

CASE 敘述

  • Simple CASE:依字面值分支。
  • Searched CASE:依運算式值分支(彈性較大)。
CASE
  WHEN years > 30 THEN SET inc = 0.08;
  WHEN years > 20 THEN SET inc = 0.07;
  WHEN years > 10 THEN SET inc = 0.05;
  ELSE SET inc = 0.04;
END CASE;

迴圈敘述

類型語法骨架特點
LOOPlabel: LOOP ... LEAVE label; END LOOP label;簡單無條件迴圈,需自行 LEAVE
WHILEWHILE condition DO ... END WHILE;前測試,條件為真才進入
REPEATREPEAT ... UNTIL condition END REPEAT;後測試,至少執行一次
FORFOR loop_name AS SELECT ... DO ... END FOR;隱式游標迴圈,自動 OPEN/FETCH/CLOSE,可用 loop_name.col 直接引用欄值

三種迴圈實作同一邏輯範例

從 EMPLOYEE 讀取指定部門員工姓名、到職日、生日,寫入 REPORT_INFO_DEPT。

-- 1. LOOP + FETCH + CONTINUE HANDLER
CREATE PROCEDURE leave_loop (deptin CHAR(3), OUT cnt INT)
L1: BEGIN
  DECLARE v_end, v_cnt INT DEFAULT 0;
  DECLARE v_lname VARCHAR(15); DECLARE v_hired, v_birth DATE;
  DECLARE c1 CURSOR FOR SELECT lastname, hiredate, birthdate FROM employee WHERE workdept = deptin;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_end = 1;
  OPEN c1;
  fetch_loop: LOOP
    FETCH c1 INTO v_lname, v_hired, v_birth;
    IF v_end <> 0 THEN LEAVE fetch_loop; END IF;
    SET v_cnt = v_cnt + 1;
    INSERT INTO report_info_dept VALUES (v_lname, v_hired, v_birth);
  END LOOP fetch_loop;
  SET cnt = v_cnt;
END L1

-- 2. WHILE 迴圈
CREATE PROCEDURE dept_rept (deptin CHAR(3), OUT cnt INT)
P1: BEGIN
  DECLARE v_end, v_cnt INT DEFAULT 0;
  DECLARE v_lname VARCHAR(15); DECLARE v_hired, v_birth DATE;
  DECLARE c1 CURSOR FOR SELECT lastname, hiredate, birthdate FROM employee WHERE workdept = deptin;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_end = 1;
  OPEN c1;
  FETCH c1 INTO v_lname, v_hired, v_birth;
  WHILE v_end = 0 DO
    INSERT INTO report_info_dept VALUES (v_lname, v_hired, v_birth);
    SET v_cnt = v_cnt + 1;
    FETCH c1 INTO v_lname, v_hired, v_birth;
  END WHILE;
  SET cnt = v_cnt;
END P1

-- 3. FOR 迴圈(最簡潔)
CREATE PROCEDURE dept_rept1 (deptin CHAR(3), OUT cnt INT)
P1: BEGIN
  DECLARE v_cnt INT DEFAULT 0;
  FOR dept_loop AS SELECT lastname, hiredate, birthdate FROM employee WHERE workdept = deptin DO
    INSERT INTO report_info_dept VALUES (dept_loop.lastname, dept_loop.hiredate, dept_loop.birthdate);
    SET v_cnt = v_cnt + 1;
  END FOR;
  SET cnt = v_cnt;
END P1

異常處理機制

宣告具名條件

DECLARE condition-name CONDITION FOR SQLSTATE 'state-string';
-- 例
DECLARE foreign_key_violation CONDITION FOR SQLSTATE '23503';
DECLARE overflow CONDITION FOR SQLSTATE '22003';

宣告條件處理器

DECLARE [CONTINUE | EXIT | UNDO] HANDLER FOR condition-value
  SQL-procedure-statement;

condition-value ::= SQLSTATE 'xxxxx' | condition-name | SQLEXCEPTION | SQLWARNING | NOT FOUND
  • CONTINUE:處理後繼續下一條敘述。
  • EXIT:處理後離開當前複合敘述區塊。
  • UNDO:回滾區塊內變更後離開(需區塊標記為 ATOMIC)。

範例:EXIT 處理器回傳錯誤碼

CREATE PROCEDURE simple_error (IN new_job CHAR(8), IN p_empno CHAR(6),
  OUT p_state CHAR(5), OUT p_code INT)
BEGIN
  DECLARE SQLCODE INT DEFAULT 0;
  DECLARE SQLSTATE CHAR(5) DEFAULT '00000';
  DECLARE EXIT HANDLER FOR SQLEXCEPTION
    SELECT SQLSTATE, SQLCODE INTO p_state, p_code FROM SYSIBM.SYSDUMMY1;
  UPDATE employee SET job = new_job WHERE empno = p_empno;
END

範例:CONTINUE 處理器實現截斷重試

CREATE PROCEDURE proc1 (IN num INT, IN new_status VARCHAR(10))
P1: BEGIN
  DECLARE SQLCODE INT DEFAULT 0; DECLARE SQLSTATE CHAR(5) DEFAULT '';
  DECLARE v_trunc INT DEFAULT 0;
  DECLARE overflow CONDITION FOR SQLSTATE '22001';  -- 字串截斷
  DECLARE CONTINUE HANDLER FOR overflow
  BEGIN
    INSERT INTO tab1 VALUES (num, SUBSTR(new_status,1,5));
    SET v_trunc = 2;
  END;
  INSERT INTO tab1 VALUES (num, new_status);
  RETURN v_trunc;
END P1

輸入過長字串觸發 22001,處理器截斷後寫入並設旗標,過程正常結束。

主動拋出例外:SIGNAL

SIGNAL SQLSTATE '72001' SET MESSAGE_TEXT = 'INPUT VALUE TOO LONG';
-- 或使用具名條件
DECLARE over_len CONDITION FOR SQLSTATE '72001';
SIGNAL over_len SET MESSAGE_TEXT = '自訂錯誤訊息';
  • 用戶自訂 SQLSTATE 必須為 5 碼,首碼為 7/8/9 或 I-Z。
  • 可選 SET MESSAGE_TEXT 附加診斷文字。

本章小結

掌握 SQL PL 核心:變數/陣列宣告與指派、特殊暫存器、游標與結果集、IF/CASE 分支、四種迴圈(特別是 FOR 隱式游標)、條件與處理器宣告、SIGNAL 主動拋出。這是撰寫健壯存儲過程、函數、觸發器的基石,也是 Exam 735 的必考重點。

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