簡單關鍵字替換 (TO_DATE → CONVERT) 只能處理平坦 SQL。真實專案中 SQL 多層巢狀、函數嵌套、Outer Join 語法差異大 (Oracle (+) vs ANSI LEFT JOIN),單純字串替換會產生無數 if-else、難以維護且極易出錯。必須採用 編譯器前端技術:詞法分析 → 語法分析 → AST → 目標語法重寫。
SelectStatement, JoinClause, FunctionCall, WhereCondition 等。
ISqlNode (Accept(visitor), Children())。
ISqlVisitor:VisitSelect, VisitJoin, VisitFunction 等。TSqlServerVisitor, TSybaseVisitor, TMySQLVisitor。node.Accept(visitor),Visitor 內部依目標語法組裝輸出字串。範例:Outer Join 轉換
// Oracle: SELECT a.*, b.* FROM a, b WHERE a.id = b.id(+)
// AST: JoinClause(LeftOuter, a.id = b.id)
// TSqlServerVisitor.VisitJoin():
IF join.Type = LeftOuter THEN
OUTPUT "LEFT JOIN " + join.RightTable + " ON " + join.Condition
ELSE IF join.Type = RightOuter THEN
OUTPUT "RIGHT JOIN " + ...
END IF
新增目標平台只需新增 Visitor 類別,不修改 AST 結構,符合開放封閉原則。
START, IN_IDENTIFIER, IN_NUMBER, IN_STRING, IN_COMMENT, IN_MULTILINE_COMMENT。Regex / System.Text.RegularExpressions 可快速實作;或手寫 FSM 獲最高效能。[SQL 字串] ↓ (Tokenizer / FSM) [Token Stream] ↓ (Parser / Interpreter) [AST (Composite Tree)] ↓ (Visitor: TSqlServerVisitor) [目標 SQL 字串]
| Oracle | SQL Server | 處理方式 |
|---|---|---|
TO_DATE(str, fmt) | CONVERT(DATETIME, str, style) | Function Visitor 映射 + 格式轉換表 |
SYSDATE | GETDATE() | Function Visitor 直接替換 |
NVL(a,b) | ISNULL(a,b) | Function Visitor (參數順序相同) |
DECODE | CASE WHEN ... THEN ... ELSE ... END | Visitor 重寫為 Case 運算式 |
(+) Outer Join | LEFT/RIGHT JOIN ... ON | JoinClause Visitor 結構化重寫 |
ROWNUM | ROW_NUMBER() OVER / TOP | 需語意分析上下文 |
DUAL | (移除 FROM 子句) | SelectStatement Visitor 過濾 |
/* UNSUPPORTED: ... */ 供人工介入。SQL 翻譯器本質是「編譯器前端」。採用 Interpreter + Composite + Visitor 三模式組合,配合 FSM 詞法分析,可建構可擴充、可維護、高正確率的異構 SQL 轉換引擎。這不只是工具,更是編譯原理在工程落地的經典實踐。