怎樣寫出可以在各個數(shù)據(jù)庫中都能執(zhí)行的SQL?
不同類型數(shù)據(jù)庫的函數(shù)語法或多或少存在差異,要想讓功能相同的 SQL 查詢語句在不同類型的數(shù)據(jù)庫中都能被順利執(zhí)行,就要把各數(shù)據(jù)庫都有的那些差異化函數(shù)語法進(jìn)行翻譯。
使用 ORM 技術(shù)能夠?qū)⒊绦騿T書寫的查詢轉(zhuǎn)換成不同數(shù)據(jù)庫的 SQL,相當(dāng)于有一定的移植能力。但 ORM 技術(shù)只適合應(yīng)對 OLTP 場景下的簡單 SQL,難以實現(xiàn) OLAP 場景下較復(fù)雜 SQL 的移植,例如,使用了 ORM 技術(shù)中不直接支持的函數(shù),或者遇到 FROM 中包含子查詢的復(fù)雜 SQL。
集算器 SPL 設(shè)計了一套標(biāo)準(zhǔn)的 SQL 查詢語法,該語法內(nèi)置大量函數(shù)(還在持續(xù)追加中),可描述更多常運算。SPL 中有一個 sqltranslate 函數(shù),可以把這種標(biāo)準(zhǔn) SQL 翻譯成不同數(shù)據(jù)庫的 SQL,實現(xiàn)數(shù)據(jù)庫的遷移。
比如這樣的標(biāo)準(zhǔn) 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
可以看到,標(biāo)準(zhǔn)函數(shù)能夠正確地根據(jù)數(shù)據(jù)庫選擇相應(yīng)的函數(shù)。
SPL 實現(xiàn) SQL 移植,采取的策略是只對標(biāo)準(zhǔn) SQL 中的函數(shù)進(jìn)行翻譯,不翻譯(原樣照抄)語句,從而使標(biāo)準(zhǔn) SQL 可描述更多的運算。比如,對于下面的子查詢無論翻譯成哪種數(shù)據(jù)庫 SQL 都不會變,也都可以正常執(zhí)行。
- SELECT
- ORDERID,
- M
- FROM
- (
- SELECT
- ORDERID,
- MONTH(ORDERDATE) M
- FROM
- ORDERS) T1
集算器 SPL 是 Java 寫的開源軟件,很容易被 JAVA 應(yīng)用 集成而使用這個 SQL 移植的功能,在應(yīng)用程序中如果需要翻譯 SQL 語句,可以直接調(diào)用 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”);