怎樣寫出可以在各個數據庫中都能執行的SQL?
不同類型數據庫的函數語法或多或少存在差異,要想讓功能相同的 SQL 查詢語句在不同類型的數據庫中都能被順利執行,就要把各數據庫都有的那些差異化函數語法進行翻譯。
使用 ORM 技術能夠將程序員書寫的查詢轉換成不同數據庫的 SQL,相當于有一定的移植能力。但 ORM 技術只適合應對 OLTP 場景下的簡單 SQL,難以實現 OLAP 場景下較復雜 SQL 的移植,例如,使用了 ORM 技術中不直接支持的函數,或者遇到 FROM 中包含子查詢的復雜 SQL。
集算器 SPL 設計了一套標準的 SQL 查詢語法,該語法內置大量函數(還在持續追加中),可描述更多常運算。SPL 中有一個 sqltranslate 函數,可以把這種標準 SQL 翻譯成不同數據庫的 SQL,實現數據庫的遷移。
比如這樣的標準 SQL:
- SELECT CLIENT, YEAR(ORDERDATE), SUM(AMOUNT)
- , COUNT(ORDERID)
- FROM ORDERS
- GROUP BY CLIENT, YEAR(ORDERDATE)
- HAVING SUM(AMOUNT) > 2000
用.sqltranlate(“MYSQL”) 翻譯后就得到:
- SELECT CLIENT, YEAR(ORDERDATE), SUM(AMOUNT)
- , COUNT(ORDERID)
- FROM ORDERS
- GROUP BY CLIENT, YEAR(ORDERDATE)
- HAVING SUM(AMOUNT) > 2000
而如果使用.sqltranslate(“ORACLE”) 將返回:
- SELECT CLIENT, EXTRACT(YEAR FROM ORDERDATE), SUM(AMOUNT)
- , COUNT(ORDERID)
- FROM ORDERS
- GROUP BY CLIENT, EXTRACT(YEAR FROM ORDERDATE)
- HAVING SUM(AMOUNT) > 2000
可以看到,標準函數能夠正確地根據數據庫選擇相應的函數。
SPL 實現 SQL 移植,采取的策略是只對標準 SQL 中的函數進行翻譯,不翻譯(原樣照抄)語句,從而使標準 SQL 可描述更多的運算。比如,對于下面的子查詢無論翻譯成哪種數據庫 SQL 都不會變,也都可以正常執行。
- SELECT
- ORDERID,
- M
- FROM
- (
- SELECT
- ORDERID,
- MONTH(ORDERDATE) M
- FROM
- ORDERS) T1
集算器 SPL 是 Java 寫的開源軟件,很容易被 JAVA 應用 集成而使用這個 SQL 移植的功能,在應用程序中如果需要翻譯 SQL 語句,可以直接調用 api 方法:
- String sql = “SELECT CLIENT, YEAR(ORDERDATE), SUM(AMOUNT) , COUNT(ORDERID) FROM ORDERS GROUP BY CLIENT, YEAR(ORDERDATE) HAVING SUM(AMOUNT) > 2000”;
- sql = com.raqsoft.dm.sql.SQLUtil.translate(sql, “ORACLE”);