PowerBuilder 提供四種動態 SQL 格式,依「有無輸入參數」與「有無結果集」組合選用。
| 格式 | 輸入參數 | 結果集 | 適用場景 |
|---|---|---|---|
| 格式 1 | 無 | 無 | DDL、單次 DML、無參數操作 |
| 格式 2 | 有 | 無 | 參數化 DML、批次操作 |
| 格式 3 | 有 | 有 (編譯期確定) | 參數化查詢、游標逐列處理 |
| 格式 4 | 有 | 有 (執行期確定) | 完全動態查詢、欄位/表名變動 |
' 語法
EXECUTE IMMEDIATE SQLStatement {USING TransactionObject};
' 範例 1:建表
EXECUTE IMMEDIATE 'CREATE TABLE base(code CHAR(6), name CHAR(30))' USING SQLCA;
' 範例 2:變數 SQL
STRING ls_sql
ls_sql = "INSERT INTO base VALUES('320201', '市中區支行')"
EXECUTE IMMEDIATE :ls_sql USING SQLCA;
' 語法
PREPARE DynamicStagingArea FROM SQLStatement {USING TransactionObject};
EXECUTE DynamicStagingArea {USING ParameterList};
' 範例:參數化刪除
STRING ls_code = "320101"
PREPARE SQLSA FROM "DELETE FROM base WHERE code = ?";
EXECUTE SQLSA USING :ls_code;
SQLSA 為 PB 內建全域 DynamicStagingArea 變數。
' 語法
DECLARE cursor_name DYNAMIC CURSOR FOR DynamicStagingArea;
PREPARE DynamicStagingArea FROM SQLStatement {USING TransactionObject};
OPEN DYNAMIC cursor_name {USING ParameterList};
FETCH cursor_name INTO VariableList;
...
CLOSE cursor_name;
' 範例:查詢 code 中間兩碼為 '01' 的記錄
STRING ls_sql, ls_code, ls_name, ls_filter = "01"
ls_sql = "SELECT code, name FROM base WHERE SUBSTRING(code, 3, 2) = ?"
DECLARE cursor_base DYNAMIC CURSOR FOR SQLSA;
PREPARE SQLSA FROM :ls_sql;
OPEN DYNAMIC cursor_base USING :ls_filter;
FETCH cursor_base INTO :ls_code, :ls_name;
DO WHILE SQLCA.SQLCODE = 0
' 處理每列邏輯
FETCH cursor_base INTO :ls_code, :ls_name;
LOOP
CLOSE cursor_base;
' 適用:SELECT 清單、FROM 表名、WHERE 條件皆在執行期決定
' 需使用 DESCRIBE 動態描述結果集結構,配合 DynamicDescriptionArea
' 較複雜,僅在極度靈活需求 (如即時查詢工具) 時使用
USING SQLCA 或自訂 TransactionObject,避免隱含交易SQLCA.SQLCODE,SQLDBCode 針對資料庫錯誤碼CLOSE,否則洩露資源導致連線耗盡? 為佔位符,:var 綁定變數| 錯誤 | 原因 | 對策 |
|---|---|---|
| SQLCODE = -1 (Syntax Error) | 動態 SQL 字串拼接錯誤、保留字衝突 | 輸出 SQL 字串至日誌、在資料庫工具驗證 |
| SQLCODE = -201 (Cursor not open) | FETCH 前未 OPEN 或已 CLOSE | 檢查邏輯流程、確保 OPEN 成功才進入迴圈 |
| 參數綁定失敗 | 參數順序/型別/數量不符 | PREPARE 時的 ? 數量 = USING 變數數量,型別相容 |
| 交易未提交/回滾 | 動態 SQL 執行後未 COMMIT/ROLLBACK | 統一在業務邏輯層控制交易邊界 |
動態 SQL 是雙面刃:靈活但危險。**參數化 (格式 2/3) + 嚴格錯誤處理 + 交易控制**是安全使用的關鍵。