專案遷移或多資料庫支援場景下,常需實現 Oracle 與 DB2 的 SQL 相容。本文針對 DB2 9.7 啟用 PLSQL 編譯選項後建立的資料庫,整理關鍵相容性差異與改寫技巧。
Oracle 支援字串串接後直接 LIKE,DB2 需改用 LOCATE 判斷子字串位置。
-- Oracle 寫法
SELECT * FROM fw_right a WHERE '03' LIKE a.rightid || '%';
-- 相容寫法 (LOCATE 回傳找到位置,1 為開頭)
SELECT * FROM fw_right a WHERE LOCATE('03', a.rightid) = 1;
-- Oracle 寫法 (包含關係)
SELECT * FROM fw_right a WHERE '03' LIKE '%' || a.rightid || '%';
-- 相容寫法
SELECT * FROM fw_right a WHERE LOCATE('03', a.rightid) > 0;
DB2 嚴格限制視圖選取清單中的別名不得與參與查詢的任何資料表欄位重名,否則拋出 SQL0153N 錯誤。
-- 錯誤範例:start_time、complete_time 為資料表既有欄位
CREATE OR REPLACE VIEW V_WF_TODOLIST AS
SELECT ...,
TO_CHAR(TO_DATE(a.start_time, 'yyyymmddhh24miss'),'yyyy-mm-dd hh24:mi:ss') AS start_time,
TO_CHAR(TO_DATE(a.complete_time,'yyyymmddhh24miss'),'yyyy-mm-dd hh24:mi:ss') AS complete_time
FROM ...;
-- 正確寫法:別名加後綴區分
CREATE OR REPLACE VIEW V_WF_TODOLIST AS
SELECT ...,
TO_CHAR(TO_DATE(a.start_time, 'yyyymmddhh24miss'),'yyyy-mm-dd hh24:mi:ss') AS start_time_0,
TO_CHAR(TO_DATE(a.complete_time,'yyyymmddhh24miss'),'yyyy-mm-dd hh24:mi:ss') AS complete_time_0
FROM ...;
DB2 不允許在下列物件的最外層查詢使用 ORDER BY 或 FETCH FIRST n ROWS ONLY:
RETURN 語句違反將報 SQL20211N 錯誤。解決方法:用子查詢包裹排序邏輯。
-- 錯誤:視圖直接 ORDER BY
CREATE OR REPLACE VIEW V_FW_BLANK_BULLETIN AS
SELECT ... FROM fw_bulletin WHERE ... ORDER BY ifergency DESC, id DESC, duetime DESC;
-- 正確:子查詢排序後再選取
CREATE OR REPLACE VIEW V_FW_BLANK_BULLETIN AS
SELECT * FROM (
SELECT ... FROM fw_bulletin WHERE ... ORDER BY ifergency DESC, id DESC, duetime DESC
);
VARCHAR2 ↔ DB2 VARCHAR;NUMBER ↔ DECIMAL;DATE ↔ TIMESTAMP。SEQUENCE ↔ DB2 SEQUENCE (語法高度相容)。SYSDATE ↔ DB2 CURRENT TIMESTAMP。OFFSET ... FETCH、DB2 原生支援 FETCH FIRST ... ROWS ONLY。掌握 LOCATE 替代 LIKE、視圖別名避免衝突、頂層排序子查詢化,即可解決 90% 以上的 Oracle-to-DB2 相容性問題。建議開發階段即在 DB2 環境持續驗證,降低遷移風險。