兩者皆在 ANSI SQL-92 基礎上擴展,移植核心在於「非標準語法」的對應轉換。
| 場景 | Oracle | SQL Server | 備註 |
|---|---|---|---|
| 無表單純運算 | SELECT 'x' FROM dual | SELECT 'x' | Oracle 必須有 FROM,DUAL 為單列單欄系統表 |
| 字串串接 | 'A' || 'B' | 'A' + 'B' | |
| 截取數字 | TRUNC(15.79, 1) | ROUND(15.79, 1, 1) 或 FLOOR | SQL Server ROUND 第 3 參數 1 表截斷 |
| 數字轉字串 | TO_CHAR(123.45, '999999.99') | STR(123.45, 10, 2) / FORMAT (2012+) | TO_CHAR 格式模板極豐富 |
| 日期時間 | SYSDATE | GETDATE() | |
| 日期加減月 | ADD_MONTHS(SYSDATE, 12) | DATEADD(MONTH, 12, GETDATE()) | |
| 日期差值(天) | SYSDATE - ADD_MONTHS(SYSDATE,12) | DATEDIFF(DAY, GETDATE(), DATEADD(MONTH,12,GETDATE())) | Oracle 直接相減得數值 |
| 字串長度 | LENGTH(str) | LEN(str) | |
| 空值判斷 | NVL(col, 0) | ISNULL(col, 0) / COALESCE | COALESCE 為 ANSI 標準,跨平台通用 |
| 條件表達式 | CASE WHEN ... THEN ... ELSE ... END | 同 ANSI 標準 | Oracle 另支援 DECODE |
| 分頁查詢 | ROW_NUMBER() OVER (ORDER BY ...) (12c+ OFFSET ... FETCH) | OFFSET ... ROWS FETCH NEXT ... ROWS ONLY (2012+) | 舊版 Oracle 用 ROWNUM 子查詢 |
| 合併結果集 | UNION / UNION ALL / MINUS / INTERSECT | UNION / UNION ALL / EXCEPT / INTERSECT | MINUS → EXCEPT |
| 外部連接 | (+) 舊語法 / ANSI LEFT JOIN | *= 舊語法 / ANSI LEFT JOIN | 統一用 ANSI JOIN 避免移植陷阱 |
-- Oracle
SELECT 1 FROM dual WHERE NULL = NULL; -- 無資料
SELECT 1 FROM dual WHERE NULL IS NULL; -- 1
SELECT 1 FROM dual WHERE NVL(NULL,0)=NVL(NULL,0); -- 1
-- SQL Server
SELECT 1 WHERE NULL = NULL; -- 無資料 (ANSI 模式)
SELECT 1 WHERE NULL IS NULL; -- 1
SELECT 1 WHERE ISNULL(NULL,0)=ISNULL(NULL,0); -- 1
重點:任何與 NULL 的比較(=、<>、>、<)皆為 UNKNOWN,必須用 IS NULL / IS NOT NULL 或 NVL/ISNULL/COALESCE 處理。
(+)/*=,消除語法與語義差異。ADD_MONTHS、MONTHS_BETWEEN 等包裝函數。SUBSTR → SUBSTRING、INSTR → CHARINDEX、REPLACE 同名但參數順序不同。SEQUENCE / IDENTITY (12c+) ↔ SQL Server IDENTITY / SEQUENCE (2012+)。EXCEPTION WHEN ... ↔ T-SQL TRY...CATCH + RAISERROR/THROW。ora2pg、sqlines 可批次轉換 DDL/DML。語法轉換只是移植的第一步;資料型別對應、鎖機制差異、優化器行為、權限模型、高可用架構才是專案成敗的關鍵。建議成立「異構資料庫移植規範」文件,持續沉澱專案經驗。