隨著業務增長,MySQL 在高併發、大數據量下出現連接緩慢、甚至宕機,需遷移至 Oracle。應用層需同步改造,以下總結八大必改項。
MySQL:id INT AUTO_INCREMENT 插入時忽略該字段。
Oracle:需創建序列並通過觸發器或顯式調用賦值:
CREATE SEQUENCE seq_tablename INCREMENT BY 1 START WITH 1 MAXVALUE 999999 NOCACHE;
-- 觸發器自動填充
CREATE OR REPLACE TRIGGER trg_tablename_bir
BEFORE INSERT ON tablename FOR EACH ROW
BEGIN SELECT seq_tablename.NEXTVAL INTO :NEW.id FROM dual; END;
-- 或 SQL 顯式調用
INSERT INTO tablename (id, col) VALUES (seq_tablename.NEXTVAL, 'val');
MySQL 支持雙引號包裹字符串,Oracle 僅認單引號。插入/更新前必須將單引號轉義為雙單引號:' → ''。
MySQL:LIMIT offset, count 簡潔高效。
Oracle:無直接語法,需雙層子查詢控制 ROWNUM:
-- 方案一:IN 子查詢
SELECT * FROM (
SELECT a.*, ROWNUM rn FROM (
SELECT * FROM table WHERE cond ORDER BY sort_col
) a WHERE ROWNUM <= :end_row
) WHERE rn > :start_row;
-- 方案二:內聯視圖(性能通常更優)
SELECT * FROM (
SELECT b.*, ROWNUM rn FROM (
SELECT * FROM table WHERE cond ORDER BY sort_col
) b
) WHERE rn BETWEEN :start_row AND :end_row;
注意:ROWNUM 僅支持 <= 或 <,不支持 > 直接過濾。
Oracle VARCHAR2 最大 4000 字節。超長文本必須定義 CLOB 類型,寫入時使用 DBMS_LOB 包:
INSERT INTO t (clob_col) VALUES (EMPTY_CLOB()) RETURNING clob_col INTO :lob_loc;
DBMS_LOB.WRITE(:lob_loc, length, 1, 'long text...');
應用層需增加非空、長度校驗,超限提前攔截。
MySQL 分離 DATE/TIME,Oracle DATE 包含年月日時分秒。
常用轉換:
-- 當前時間
SYSDATE
-- 字符串轉日期
TO_DATE('2024-01-15', 'YYYY-MM-DD')
TO_DATE('2024-01-15 14:30:00', 'YYYY-MM-DD HH24:MI:SS')
-- 日期轉字符串
TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS')
-- 7 天前數據
WHERE date_col > SYSDATE - 7 -- Oracle 直接數學運算
-- MySQL 寫法對比
WHERE date_col > DATE_SUB(NOW(), INTERVAL 7 DAY)
MySQL 允許 NOT NULL 列存空字符串 '',Oracle 視 '' 等同 NULL,導入時需將空串轉為單空格 ' ' 或實際 NULL,否則 NOT NULL 約束報錯。
WHERE col LIKE '%keyword%' 導致全表掃描。Oracle 推薦:
WHERE INSTR(col, 'keyword') > 0 可利用函數索引,精確且高效。
Oracle 服務端游標資源較寶貴,應用層(Java/PDO/OCI)務必在 finally 塊中關閉 ResultSet、Statement、Connection,防止游標泄漏導致 ORA-01000。
AUTO_INCREMENT 重構為 Sequence + Trigger