在實際業務中經常需要拼接動態SQL來完成復雜數據計算,網上各類技術論壇都有討論,比如下面這些問題:
http://bbs.csdn.net/topics/390876591
http://bbs.csdn.net/topics/390981627
http://bbs.csdn.net/topics/390073758
http://bbs.csdn.net/topics/390611005
拼接動態SQL的一般做法有
1、使用動態語句
很多數據庫都提供了處理動態SQL的語法,如Oracle的EXECUTE IMMEDIATE語句、MSSQL的EXEC和SP_EXECUTESQL、Mysql的預處理語句等。這些功能讓我們在數據庫端來處理動態查詢提供了極大遍歷,但這種方式只適用於相對簡單地動態查詢,復雜的情況經常會采用下面的方式。
2、使用存儲過程
對於復雜的情況,一般會在存儲過程中來拼接動態SQL。使用存儲過程完成相對靈活,但編碼復雜度過高,有時運行效率較低。
3、使用其他(如JAVA)程序
使用外部的其他高級語言(如JAVA)拼接后再交由數據庫執行也是一種選擇,其靈活性較高,但由於JAVA缺乏對集合計算的支持,完成這些准備工作並不輕松。
如果需要執行動態SQL的主控程序是JAVA的,那么可以使用集算器來協助完成動態SQL類計算,集算器是動態解釋執行的腳本,可以方便地拼出動態SQL執行。集算器提供了JDBC接口,可以置於Java應用程序與數據庫之間,讓應用程序繼續象訪問數據庫一樣執行集算器腳本,應用結構幾乎不用改變。
下面通過例子來說明如何使用集算器完成動態SQL類計算,並集成進JAVA程序。
拼接動態SQL
在集算器中完成動態SQL拼接,並將拼接后的SQL再交由數據庫執行,以查詢出目標結果。集算器在完成時並不涉及目標計算,只拼接動態SQL。如下面的需求:
參數source和target代表兩個結構相同但數據不同的表,但表結構未知。要求以主鍵為標准用source更新target,比如table1和table2的主鍵都是A和B,數據如下:
用table2更新table1時,MERGE語句應當如下:
MERGE INTO table1 as t
USING table2 as s
ON t.A=s.A and t.B=s.B
WHEN MATCHED
THEN UPDATE SET t.C=s.C,t.D=s.D
WHEN NOT MATCHED
THEN INSERT VALUES(s.A,s.B,s.C,s.D)
實現腳本:
A1,A2: 從系統表中讀出表source的主鍵存入變量pks,計算結果為集合["A","B"]。各種數據庫獲得主鍵的方法不同,這里以MSSQL為例。
A3,A4:讀出source的完整字段,columns的計算結果為["A","B","C","D"]。
A5:動態生成MERGE語句。pks.(…)是循環函數,可對集合(包括結果集)的成員依次計算,計算中可用~引用循環變量,用#引用循環計數。
A6:執行MERGE語句。
由於表結構未知,用存儲過程或JAVA獲得表結構再動態拼出SQL非常麻煩。使用集合類計算支持良好的集算器來做,代碼簡單,腳本通用,易於維護。
集算腳本的計算結果可以作為報表數據源供報表使用,還可以在JAVA程序中通過JDBC的方式讀取並使用,JAVA讀取調用集算腳本代碼如下:
Class.forName("com.esproc.jdbc.InternalDriver");
con= DriverManager.getConnection("jdbc:esproc:local://");
//調用集算器腳本(類似存儲過程),其中p1是集算腳本的文件名
st =(com. esproc.jdbc.InternalCStatement)con.prepareCall("call p1()");
st.setObject(1,"table1");
st.setObject(2," table2");
//執行腳本
st.execute();
……
調用集算器腳本和訪問數據庫的方法完全一樣,熟悉JDBC的程序員可以很快掌握。
關於集算器JDBC的部署和調用的更詳細信息可參考集算器集成應用之被JAVA調用。
動態表間連接
相對靜態的表間連接,動態表間連接事先並不知道要使用的表。如下面的數據查詢:
A表
B表
C表
現需要根據A表的TableName獲取B表或C表對應ID的Num值。
目標結果:
實現腳本:
A1:執行SQL從A表取數;
A2:先按TableName分組,循環分組拼接動態查詢語句,最后把查詢結果按照ID排序。
通過集算器的集合計算能力(分組后仍然保存着分組成員供后續使用),讓動態SQL的拼接工作簡單化。
特殊格式數據更新
除了動態數據查詢,有時還需要進行動態更新,更新的數據經常來源於第三方程序,其格式也多種多樣,如JSON格式、XML等。在特殊的業務背景下,有時需要將這些較特殊格式(相對傳統的二維表來說)的數據更新到(關系)數據庫中。這就需要借助第三方程序完成,而像JAVA等高級語言存在缺少類庫、硬編碼困難等問題。這時可以采用集算器來完成,下面來看一個集算器解析JSON格式文件入庫的例子,源數據如下:
要求:將上述內容中指定節點,主要是imei的Service列表更新到數據庫2張表groups和Services中。
這里的JSON串由於包含多層且很多層都是動態的(如LIST和SERVICES下的節點數量和名稱都不固定),這為解析帶來了很大難度;而且其中屬性名部分還包含空格(如MOVISTAR SPAIN)和點號(如Requires.Network)這也大大增加了解析難度,使用JAVA非常難寫。
實現腳本:
A1:讀入JSON格式文件,結果為帶有層次的結果集;
A2-A3:創建存儲更新內容的兩個空序表;
A4-D10:循環A1,動態解析內容並將解析結果輸出到A2、A3目標結果序表中;
A11-A12:執行更新,將A2、A3序表更新到groups和services表中。
http://datamachine.iteye.com/blog/2219100