專案需將 Oracle 環境移植至 MySQL(Linux),**核心原則:不改應用代碼,僅調整 DDL/初始化腳本**。實戰中遇到的 5 大類差異及解法如下。
| 場景 | Oracle | MySQL (Linux) |
|---|---|---|
| 未加引號 | 不區分大小寫,內部轉大寫 | **區分大小寫**(表名對應目錄,列名對應檔案) |
| 加雙引號 | 區分大小寫,保持原樣 | 區分大小寫,保持原樣 |
解法:
order_items),DDL、SQL、代碼全域一致。--lower-case-table-names=1(需實例級配置)。Oracle 允許保留字作識別符(如 INTERVAL, SHOW),MySQL 直接報語法錯誤。
解法:
INSERT INTO t (id, \`interval\`) VALUES (...)INSERT INTO t (id, t.interval) VALUES (...)_(如 _interval)。| Oracle | MySQL | 備註 |
|---|---|---|
| VARCHAR2(n) | VARCHAR(n) | MySQL 5.0+ VARCHAR 支援 65535 位元組 |
| NUMBER(p,s) | DECIMAL(p,s) / NUMERIC(p,s) | MySQL 無精度無標度的 NUMBER 等價型別 |
| DATE | DATETIME | Oracle DATE 含時間,MySQL DATE 僅日期 |
| TIMESTAMP | TIMESTAMP | MySQL TIMESTAMP 範圍 1970-2038,跨世紀用 DATETIME |
| CLOB/BLOB | LONGTEXT/LONGBLOB | MySQL TEXT 族群分級更細 |
| RAW | VARBINARY / BINARY |
| Oracle | MySQL |
|---|---|
SEQUENCE + Trigger / 代碼手動 .NEXTVAL | AUTO_INCREMENT 欄位屬性 |
遷移策略:
BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY。seq_migrate(seq_name, last_val),應用啟動時同步 AUTO_INCREMENT = last_val + 1。解法:
VARCHAR(255) → VARCHAR(191))。INDEX idx_name (col(50))。DECODE→CASE, (+)→LEFT JOIN, SYSDATE→CURRENT_TIMESTAMP)。Pageable 介面,Oracle 用 ROWNUM/OFFSET FETCH,MySQL 用 LIMIT OFFSET,PostgreSQL 用 LIMIT OFFSET。type_mapping.yml,遷移腳本自動轉換。| 項目 | 驗收標準 |
|---|---|
| DDL 執行 | MySQL 5.7/8.0 無報錯建立所有物件 |
| 資料導入 | 全量資料對帳一致(行數、關鍵欄位 checksum) |
| 應用測試 | 核心業務流程 100% 通過,無 SQL 異常 |
| 效能基線 | 關鍵 SQL 執行計畫合理,慢查詢 < 1s |
| 相容性回歸 | 同一代碼包在 Oracle/MySQL 雙環境跑通測試套件 |
Oracle → MySQL 遷移,**80% 的坑在設計階段就能填平**。「不改代碼」是美好願景,現實往往需要微調 DAO 層分頁、日期處理、保留字轉義。建立**型別映射表、命名規範、分頁抽象層**三件套,才能實現真正的「寫一次,跑兩邊」。