在 DB2 游標迴圈中執行 COMMIT 會導致游標關閉,後續 FETCH 將拋出「游標未開啟」錯誤(SQLCODE -501)。游標宣告與操作必須在單一交易範圍內完成,或使用 WITH HOLD 選項跨交易保持游標(但需謹慎評估鎖持有影響)。
使用 WHILE 迴圈遍歷游標時,必須宣告 NOT FOUND 條件處理器,否則游標讀至末尾後會陷入無限迴圈,重複回傳最後一筆資料。
DECLARE v_notfound INT DEFAULT 0;
DECLARE c1 CURSOR FOR SELECT col1, col2 FROM table1;
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET v_notfound = 1;
OPEN c1;
SET v_notfound = 0;
FETCH c1 INTO v_col1, v_col2;
WHILE v_notfound = 0 DO
-- 處理邏輯
FETCH c1 INTO v_col1, v_col2;
END WHILE;
CLOSE c1;
DB2 CHAR(n) 型別擷取時會保留尾端空白至定義長度。直接比較或顯示會產生預期外結果。務必使用 TRIM() 或 RTRIM() 清理:
SET v_clean_val = TRIM(v_char_val);
若游標迴圈內呼叫的存儲程序發生錯誤(如邏輯錯誤、權限不足、資料異常),DB2 可能同樣回報「游標未開啟」而非原始錯誤碼。除錯建議:
| 項目 | 建議做法 | 風險等級 |
|---|---|---|
| 游標內 COMMIT | 嚴禁;若需分批提交,重新開啟游標或使用游標保持 | 高 |
| NOT FOUND 處理 | 必須宣告 CONTINUE HANDLER 設定旗標 | 高 |
| CHAR/RTRIM | 讀取後立即 TRIM | 中 |
| 巢狀存儲程序 | 錯誤處理完備、避免未捕獲例外 | 中 |
| 游標類型選擇 | 唯讀查詢加 FOR READ ONLY 提升效能 | 低 |
| WITH HOLD 使用 | 跨交易需求時謹慎啟用,注意鎖持有時間 | 中 |
掌握這些細節,能避開 90% 以上的 DB2 游標相關運行時錯誤,編寫健壯的 SQL PL 程式碼。