異構遷移中 SQL 重寫是核心工作量。本文系統對照 Oracle 與 DB2 在條件表達、遞歸查詢、虛擬表、日期處理、空值函數、外連接、LIKE 謂詞、隔離級別/鎖行為、分頁查詢等 9 大維度的語法差異,提供可直接套用的改寫模式與實測結論。
Oracle DECODE(expr, search1, result1, ..., default) 對應 DB2 兩種 CASE 形式:
-- 簡單 CASE
CASE expr
WHEN search1 THEN result1
...
ELSE default
END
-- 搜索 CASE
CASE
WHEN condition1 THEN result1
...
ELSE default
END
-- Oracle
SELECT DECODE(t.organtypecode, 'D', t.parent, 'S', t.parent, t.id)
FROM a_organ t WHERE t.parent = 35;
-- DB2
SELECT CASE x.organtypecode
WHEN 'D' THEN x.parent
WHEN 'S' THEN x.parent
ELSE x.id
END
FROM a_organ x WHERE x.parent = 35;
Oracle 層級查詢改寫為 DB2 遞歸公用表表達式:
-- Oracle
SELECT t.id FROM a_organ t
START WITH t.id IN (SELECT DECODE(...) FROM a_organ WHERE t.id = 35)
CONNECT BY t.parent = PRIOR t.id;
-- DB2
WITH FKK(id) AS (
SELECT o.id FROM a_organ o WHERE o.id = 35
UNION ALL
SELECT CASE x.organtypecode
WHEN 'D' THEN x.parent
WHEN 'S' THEN x.parent
ELSE x.id
END
FROM FKK fk, a_organ x
WHERE fk.id = x.parent
)
SELECT DISTINCT id FROM FKK;
-- Oracle
SELECT 15 AS ttt FROM dual;
-- DB2
SELECT 15 AS ttt FROM SYSIBM.SYSDUMMY1;
| Oracle | DB2 | 備註 |
|---|---|---|
| TO_DATE(str, fmt) | DATE(str) / TIMESTAMP_FORMAT(str, fmt) | DB2 支持 DATE('2024-05-18') 直接轉換 ISO 格式 |
| SYSDATE | CURRENT TIMESTAMP | |
| date + n | date + n DAYS | DB2 需顯式單位 |
| TRUNC(date) | DATE(date) | 去除時間部分 |
-- Oracle
WHERE m.blqsrq >= TO_DATE('$P', 'yyyy-mm-dd')
AND m.blqsrq < TO_DATE('$P', 'yyyy-mm-dd') + 1
-- DB2
WHERE DATE(m.blqsrq) >= DATE('1900-01-01')
AND DATE(m.blqsrq) < DATE('2050-01-01') + 1 DAY
NVL(expr1, expr2) → COALESCE(expr1, expr2)(標準 SQL,參數類型可異)或 VALUE(expr1, expr2)(DB2 專用,要求兩參數同類型)。NVL(num_col, '') 允許字符串默認值,DB2 VALUE(num_col, '') 會報類型錯誤,需用 COALESCE(num_col, 0) 或顯式轉換。| 類型 | Oracle (+) 符號 | DB2 / 標準 SQL |
|---|---|---|
| 內連接 | WHERE a.id = b.id | INNER JOIN ... ON a.id = b.id |
| 左外連接 | WHERE a.id = b.id(+) | LEFT OUTER JOIN ... ON a.id = b.id |
| 右外連接 | WHERE a.id(+) = b.id | RIGHT OUTER JOIN ... ON a.id = b.id |
| 全外連接 | 不支持 | FULL OUTER JOIN ... ON a.id = b.id |
DB2 pattern-expression(右側模式)不支持列引用,僅允許:常量、特殊寄存器、宿主變量、標量函數、上述項的拼接表達式。Oracle 允許列作為模式。遷移時需將動態模式改為應用層拼接後綁定參數。
測試表 RRTest:主鍵 pkID、唯一索引 unID1、普通索引 unID2、無索引列 TSID。
| 索引類型 | RR (Repeatable Read) | RS (Read Stability) |
|---|---|---|
| 主鍵 | 鎖行,不鎖表 | 鎖行,不鎖表 |
| 唯一索引 | 鎖行,不鎖表 | 鎖行,不鎖表 |
| 普通索引 | 不鎖行,不鎖表 (1) | 鎖行,不鎖表 |
| 無索引 (表掃) | 鎖行,鎖表 | 鎖行,鎖表 (2) |
(1) RR 下普通索引掃描未加鎖,原理待深究(可能因非唯一鍵範圍鎖機制差異)。
(2) RS 表掃描同 RR,鎖全表。
-- DB2 (ROW_NUMBER 標準)
SELECT * FROM (
SELECT col1, col2, col3,
ROW_NUMBER() OVER (ORDER BY sort_col ASC) AS rn
FROM tab
) AS t WHERE t.rn BETWEEN 10 AND 20;
-- 簡化:SELECT * FROM table FETCH FIRST 20 ROWS ONLY (僅首頁)