遷移工具選型
| 工具 | 適用場景 | 優點 | 缺點 |
| SQL Developer Migration Wizard | 中小型資料庫、異構遷移 | 免費、GUI、支援離線/線上、報表完整 | 大資料量慢、複雜邏輯需人工調整 |
| Oracle GoldenGate | 零停機、持續同步 | 即時、雙向、異構支援佳 | 授權成本高、架構複雜 |
| Data Pump + 外部表 | 大量資料、一次性遷移 | 高效能、平行、Server 端 | 需中間檔案、停機窗口 |
| 自訂 ETL (Python/Java) | 複雜轉換、資料清洗 | 彈性最大 | 開發維護成本高 |
SQL Developer 遷移實戰步驟
- 安裝 JDBC 驅動:下載
mysql-connector-java.jar → SQL Developer → Tools → Preferences → Database → Third Party JDBC Drivers → Add
- 建立遷移專案:Tools → Migration → Repository → Create → 設定 MySQL 連線 (Host/Port/Database/User/Pass)
- 捕獲模型:右鍵 MySQL 連線 → Capture Model → 選擇 Schema → 產生轉換模型
- 轉換模型:右鍵捕獲模型 → Convert → 生成 Oracle 模型 → 檢視轉換報表 (紅色 = 需人工處理)
- 生成 DDL:右鍵 Oracle 模型 → Generate → 儲存 .sql 檔
- 移動資料:Tools → Migration → Data Move → 線上模式 (需網路) 或離線模式 (產生載入腳本)
關鍵差異對照表
| MySQL | Oracle | 注意事項 |
| AUTO_INCREMENT | IDENTITY (12c+) / Sequence+Trigger | 遷移工具自動建 Sequence+Trigger |
| TINYINT/SMALLINT/MEDIUMINT/INT/BIGINT | NUMBER(p,s) | NUMBER(3) ~ TINYINT, NUMBER(10) ~ INT |
| DECIMAL(p,s) | NUMBER(p,s) | 相容 |
| FLOAT/DOUBLE | BINARY_FLOAT/BINARY_DOUBLE | 或 NUMBER |
| VARCHAR/TEXT | VARCHAR2 / CLOB | VARCHAR2 max 4000 (12c+ 32K) |
| DATETIME/TIMESTAMP | DATE / TIMESTAMP | DATE 含時間、精度秒;TIMESTAMP 含小數秒 |
| ENUM/SET | CHECK 約束 / 參考表 | 需人工重構 |
| ENGINE=InnoDB/MyISAM | 無對應 (表空間管理) | 忽略 |
| LIMIT n OFFSET m | OFFSET m ROWS FETCH NEXT n ROWS ONLY (12c+) | 11g 用 ROWNUM 包裹 |
| REPLACE INTO | MERGE INTO | 語法不同 |
| INSERT IGNORE | INSERT ... LOG ERRORS / MERGE | 需改寫 |
| NOW() | SYSDATE / CURRENT_TIMESTAMP | SYSDATE 回傳 DB 時間 |
| IFNULL/COALESCE | NVL / COALESCE | NVL 兩參數、COALESCE 多參數 |
| DATE_FORMAT | TO_CHAR | 格式模型不同 |
| CONCAT | || 運算子 | Oracle || 為字串串接 |
| BACKTICK ` | 雙引號 " (區分大小寫) | 建議不加引號、統一大寫 |
函數與語法轉換重點
-- 分頁
MySQL: SELECT * FROM t LIMIT 10 OFFSET 20
Oracle 12c+: SELECT * FROM t OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY
Oracle 11g: SELECT * FROM (SELECT a.*, ROWNUM rn FROM (SELECT * FROM t) a WHERE ROWNUM <= 30) WHERE rn > 20
-- 自增
MySQL: CREATE TABLE t (id INT AUTO_INCREMENT PRIMARY KEY)
Oracle: CREATE TABLE t (id NUMBER GENERATED AS IDENTITY PRIMARY KEY)
-- 字串串接
MySQL: CONCAT(a,b,c)
Oracle: a || b || c
-- 日期格式化
MySQL: DATE_FORMAT(dt, '%Y-%m-%d')
Oracle: TO_CHAR(dt, 'YYYY-MM-DD')
-- 當前時間
MySQL: NOW()
Oracle: SYSDATE (DATE) 或 CURRENT_TIMESTAMP (TIMESTAMP WITH TIME ZONE)
-- 判斷 NULL
MySQL: IFNULL(col, 0)
Oracle: NVL(col, 0) 或 COALESCE(col, 0)
遷移後驗證清單
- 物件計數:表、視圖、索引、約束、觸發器、序列、函數/程序、套件
- 資料筆數:每表
COUNT(*) 對比
- 檢查和:關鍵欄位
SUM/AVG/MIN/MAX 對比
- 應用測試:指向 Oracle 的測試環境跑完整回歸
- 效能基準:核心 SQL 執行計畫、執行時間對比
- 字符集:確認
AL32UTF8 避免亂碼
常見遷移坑與解法
| 問題 | 解決 |
| 大小寫敏感 | Oracle 預設大寫、雙引號才區分大小寫 → 統一大寫、避免雙引號 |
| 空字串 = NULL | Oracle '' 即 NULL → 應用層邏輯調整、NOT NULL 約束檢查 |
| 日期精度 | MySQL DATETIME 秒、Oracle DATE 秒、TIMESTAMP 奈秒 → 統一用 TIMESTAMP |
| 隱含轉換 | Oracle 較嚴格 → 明確 TO_DATE/TO_NUMBER/TO_CHAR |
| 鎖行為 | MySQL MVCC、Oracle 讀不阻寫寫不阻讀 → 測試並發場景 |
| 自增值不連續 | Sequence CACHE 導致 → 接受或用 NOCACHE |