Oracle PL/SQL 移植至 DB2 SQL PL 時,封裝 (PACKAGE) 語法差異是高頻阻斷點。本文剖析一個真實的 CREATE OR REPLACE PACKAGE 移植失敗案例,解析 DB2 不支援 OR REPLACE、PACKAGE 規格/主體分離定義、參數模式關鍵字差異等核心問題,並給出修正後的 DB2 相容代碼。
CREATE OR REPLACE PACKAGE "CRM_PLOG"
AS
PROCEDURE ETL_FO (
IN i_crm_name VARCHAR,
IN i_crm_type VARCHAR,
IN i_crm_fo VARCHAR,
IN i_crm_start TIMESTAMP,
IN i_crm_end TIMESTAMP
);
END CRM_PLOG;
SQL0104N 在 "CREATE PACKAGE" 後面找到異常標記 "CRM_PLOG"。預期標記可能包括: "JOIN"
根因:DB2 解析器不識別 CREATE OR REPLACE PACKAGE 這一 Oracle 專有語法,將 OR 誤認為 SQL 關鍵字,導致後續標記解析偏移。
| Oracle | DB2 (SQL PL) | 說明 |
|---|---|---|
| CREATE OR REPLACE PACKAGE | CREATE PACKAGE / CREATE PACKAGE BODY | DB2 不支援 OR REPLACE;規格與主體分離建立 |
| PACKAGE 規格與主體合寫 | 分離: 1. CREATE PACKAGE spec ... END 2. CREATE PACKAGE BODY body ... END | 強制模組化 |
| 參數模式 IN/OUT/IN OUT | IN / OUT / INOUT | DB2 用 INOUT 替代 IN OUT |
| VARCHAR 無長度 | VARCHAR(n) 必須指定長度 | DB2 強制長度 |
| 雙引號大小寫敏感 | 同支援,但建議統一大寫 | 避免識別符混淆 |
CREATE PACKAGE CRM_PLOG
AS
PROCEDURE ETL_FO (
IN i_crm_name VARCHAR(128),
IN i_crm_type VARCHAR(64),
IN i_crm_fo VARCHAR(256),
IN i_crm_start TIMESTAMP,
IN i_crm_end TIMESTAMP
);
END CRM_PLOG;
CREATE PACKAGE BODY CRM_PLOG
AS
PROCEDURE ETL_FO (
IN i_crm_name VARCHAR(128),
IN i_crm_type VARCHAR(64),
IN i_crm_fo VARCHAR(256),
IN i_crm_start TIMESTAMP,
IN i_crm_end TIMESTAMP
)
LANGUAGE SQL
BEGIN
-- 具體 ETL 邏輯實作
-- DECLARE 變數 ...
-- INSERT/UPDATE/DELETE ...
-- COMMIT;
END;
END CRM_PLOG;
OR REPLACE 關鍵字。CREATE 語句。VARCHAR、CHAR 長度。IN OUT 改為 INOUT。%TYPE、%ROWTYPE 引用是否支援 (DB2 部分支援)。GRANT EXECUTE ON PACKAGE CRM_PLOG TO USER/ROLE。s/CREATE OR REPLACE PACKAGE/CREATE PACKAGE/g 等批次替換。CREATE PACKAGE,觀察 SQLSTATE 定位錯誤行。
Package 只是移植冰山一角,函數、觸發器、匿名區塊同理。建議建立「Oracle→DB2 語法對照表」納入團隊規範,移植前先跑工具掃描,人工修正剩餘 30% 複雜邏輯。