差異對照表
| # | 維度 | MySQL | Oracle | 遷移要點 |
| 1 | 聚合函數與 GROUP BY | SELECT 非聚合列無需 GROUP BY | 非聚合列**必須**出現在 GROUP BY 或被聚合 | Oracle 遷移時補全 GROUP BY |
| 2 | 自增主鍵 | `AUTO_INCREMENT` | Sequence + Trigger / Identity (12c+) | 建 Sequence、Trigger 模擬自增 |
| 3 | 字符串引號 | 單/雙引號均可 | **僅單引號** | 雙引號→單引號;單引號轉義 `''` |
| 4 | 分頁語法 | `LIMIT offset, rows` | ROWNUM 子查詢 / OFFSET...FETCH (12c+) | MySQL 簡單;Oracle 需嵌套 ROWNUM |
| 5 | 長文本處理 | TEXT/BLOB 直接操作 | >4000 字節需 CLOB + DBMS_LOB | 大文本改用 CLOB 並用包處理 |
| 6 | 日期類型與運算 | DATE / TIME / DATETIME | DATE 含時分秒 | Oracle 用 SYSDATE、INTERVAL、日期減法直接 `- n` |
| 7 | 空值語義 | NOT NULL 列可存空字符串 `''` | NOT NULL 列**不可存空值** (含空串) | 導入前空串→空格或預設值 |
| 8 | 模糊查詢優化 | `LIKE '%str%'` 可用索引 (特定條件) | `LIKE` 不走索引,用 `INSTR(col, 'str') > 0` | Oracle 推薦 INSTR 或 Context 索引 |
| 9 | 游標/結果集釋放 | 自動/隱式管理 | **必須顯式關閉** 游標、釋放結果集 | 應用層代碼需加 finally 釋放邏輯 |
重點代碼對比
分頁:MySQL vs Oracle (11g)
-- MySQL: 簡單直接
SELECT * FROM t ORDER BY id LIMIT 20, 10;
-- Oracle 11g: 複雜嵌套
SELECT * FROM (
SELECT a.*, ROWNUM rn FROM (
SELECT * FROM t ORDER BY id
) a WHERE ROWNUM <= 30
) WHERE rn > 20;
日期運算
-- MySQL: 7 天前
WHERE dt > DATE_SUB(NOW(), INTERVAL 7 DAY)
-- Oracle: 直接相減
WHERE dt > SYSDATE - 7
自增主鍵
-- MySQL
CREATE TABLE t (id INT AUTO_INCREMENT PRIMARY KEY);
-- Oracle (傳統)
CREATE SEQUENCE seq_t_id INCREMENT BY 1 START WITH 1;
CREATE TRIGGER trg_t_bi BEFORE INSERT ON t FOR EACH ROW
BEGIN SELECT seq_t_id.NEXTVAL INTO :NEW.id FROM DUAL; END;
遷移檢查清單
- 所有 `GROUP BY` 語句補全非聚合列
- 雙引號字符串全部替換為單引號,內部單引號雙寫
- 分頁邏輯重寫為 ROWNUM 模式或 12c+ OFFSET FETCH
- 大文本字段改 CLOB,調用 `DBMS_LOB` 讀寫
- 日期函數統一轉換:`NOW()`→`SYSDATE`,`DATE_SUB`→`- INTERVAL`
- 空字符串 `''` 統一處理為 `' '` 或預設值
- 模糊查詢 `LIKE '%...%'` 改 `INSTR(...) > 0`
- 連接池/DAO 層確保 `ResultSet`/`Statement` 顯式 `close()`