從 Oracle 遷移 MySQL 或雙資料庫開發時的 9 大關鍵差異對照表,含語法、函數、行為差異與遷移建議。
差異對照總表
| # | 項目 | Oracle | MySQL | 遷移建議 |
| 1 | 群組函數 | SELECT 非群組欄位需在 GROUP BY | 允許非 GROUP BY 欄位(唯一值任取) | MySQL 啟用 ONLY_FULL_GROUP_BY 對齊 |
| 2 | 自動遞增 | Sequence + Trigger | AUTO_INCREMENT / IDENTITY | 改用 MySQL 原生自增 |
| 3 | 字串引號 | 僅單引號 'str' | 單/雙引號皆可 | 統一用單引號 |
| 4 | 分頁查詢 | ROWNUM 子查詢多層嵌套 | LIMIT offset, count | MySQL 簡潔得多 |
| 5 | 長字串 | >4000 需 CLOB + DBMS_LOB | TEXT/LONGTEXT 直支援 | MySQL 無 4000 限制 |
| 6 | 日期型別 | DATE 含時分秒,SYSDATE | DATE/TIME/DATETIME/TIMESTAMP 分離 | 注意型別對應 |
| 7 | 空字串/NULL | NOT NULL 真正禁止空值 | NOT NULL 仍可存空字串 | 匯入時空字串轉 ' ' |
| 8 | 模糊查詢 | INSTR(col, 'str')>0 可用索引 | LIKE '%str%' 不用索引 | MySQL 考慮全文索引 |
| 9 | 游標/結果集 | 嚴格要求關閉釋放 | 相對寬鬆 | 養成好習慣显式關閉 |
詳細補充說明
1. 群組函數:MySQL 5.7+ 預設啟用 ONLY_FULL_GROUP_BY
-- Oracle 必須寫
SELECT deptno, COUNT(*) FROM emp GROUP BY deptno;
-- MySQL 舊版允許(隨機取一筆 ename)
SELECT deptno, ename, COUNT(*) FROM emp GROUP BY deptno;
-- 新版報錯,需加入 GROUP BY 或用 ANY_VALUE(ename)
2. 自增:Oracle Sequence 模擬
CREATE SEQUENCE seq_emp_id INCREMENT BY 1 START WITH 1 MAXVALUE 999999;
INSERT INTO emp (id, name) VALUES (seq_emp_id.NEXTVAL, 'John');
4. 分頁:Oracle 標準寫法
SELECT * FROM (
SELECT a.*, ROWNUM rn FROM (
SELECT * FROM emp ORDER BY hiredate
) a WHERE ROWNUM <= 100
) WHERE rn > 80;
6. 日期函數對照
| 功能 | Oracle | MySQL |
| 目前時間 | SYSDATE | NOW() |
| 字串轉日期 | TO_DATE('2024-01-01','YYYY-MM-DD') | STR_TO_DATE('2024-01-01','%Y-%m-%d') |
| 日期轉字串 | TO_CHAR(sysdate,'YYYY-MM-DD HH24:MI:SS') | DATE_FORMAT(NOW(),'%Y-%m-%d %H:%i:%s') |
| 7天前 | SYSDATE - 7 | DATE_SUB(NOW(), INTERVAL 7 DAY) |
8. 模糊查詢效能
- Oracle
INSTR 可使用索引(函數索引)
- MySQL
LIKE '%str%' 導致全表掃描
- MySQL 方案:
FULLTEXT INDEX、ngram parser(中文)、外部搜尋引擎