業務增長導致 MySQL 連線數暴增、單表億級查詢緩慢,決定遷移至 Oracle 企業版。應用層以 PHP/Java 為主,需同步改造。
-- MySQL
id INT AUTO_INCREMENT PRIMARY KEY
-- Oracle
CREATE SEQUENCE seq_tbl_id INCREMENT BY 1 START WITH 1 MAXVALUE 9999999999 NOCACHE NOCYCLE;
CREATE OR REPLACE TRIGGER trg_tbl_bir
BEFORE INSERT ON tbl
FOR EACH ROW
BEGIN
SELECT seq_tbl_id.NEXTVAL INTO :NEW.id FROM dual;
END;
/
-- INSERT 時不指定 id,觸發器自動填充
-- MySQL 允許雙引號
SELECT "hello", 'world';
-- Oracle 僅單引號,單引號轉義為兩個單引號
SELECT 'hello', 'world' FROM dual;
-- 應用層寫入前:str.replace("'", "''")
-- MySQL
SELECT * FROM t ORDER BY id LIMIT 20 OFFSET 40;
-- Oracle 11g 經典寫法 (ID 為唯一鍵)
SELECT * FROM (
SELECT a.*, ROWNUM rn FROM (
SELECT * FROM t ORDER BY id
) a WHERE ROWNUM <= 60
) WHERE rn > 40;
-- Oracle 12c+ 標準語法
SELECT * FROM t ORDER BY id OFFSET 40 ROWS FETCH NEXT 20 ROWS ONLY;
-- 建表
CREATE TABLE docs (id NUMBER PRIMARY KEY, content CLOB);
-- 插入 (PL/SQL)
DECLARE
l_clob CLOB;
BEGIN
INSERT INTO docs (id, content) VALUES (1, EMPTY_CLOB()) RETURNING content INTO l_clob;
DBMS_LOB.WRITEAPPEND(l_clob, LENGTH(:long_text), :long_text);
COMMIT;
END;
/
-- 應用層:JDBC setCharacterStream / OraclePreparedStatement.setClob
| 操作 | MySQL | Oracle |
|---|---|---|
| 當前時間 | NOW() | SYSDATE / CURRENT_TIMESTAMP |
| 字串轉日期 | STR_TO_DATE('2023-01-01','%Y-%m-%d') | TO_DATE('2023-01-01','YYYY-MM-DD') |
| 日期轉字串 | DATE_FORMAT(dt,'%Y-%m-%d') | TO_CHAR(dt,'YYYY-MM-DD') |
| 7 天前 | DATE_SUB(NOW(), INTERVAL 7 DAY) | SYSDATE - 7 |
| 日期加減月 | DATE_ADD(dt, INTERVAL 1 MONTH) | ADD_MONTHS(dt, 1) |
NOT NULL 欄位可插入空字串 '' 或 0。NOT NULL 僅允許非 NULL,空字串 '' 視同 NULL(Oracle 無空字串概念)。UPDATE t SET col = ' ' WHERE col = '' OR col IS NULL;(用空格佔位)。-- MySQL
SELECT * FROM t WHERE name LIKE '%keyword%';
-- Oracle LIKE 不走索引,改用 INSTR (函數索引可加速)
SELECT * FROM t WHERE INSTR(name, 'keyword') > 0;
-- 建立函數索引
CREATE INDEX idx_t_name_instr ON t (INSTR(name, 'keyword'));
CLOSE cursor、FREE statement,防洩漏。ojdbc8.jar、PHP oci8、Python cx_Oracle。系統性處理七大差異,配合自動化驗證,讓 MySQL→Oracle 遷移可控、可驗證、可回滾。