? 引言 作為一名數(shù)據(jù)庫開發(fā)程序員,使用 SQL 語言查詢數(shù)據(jù)是再普通不過的一件事。而 SQL 語言是基于數(shù)據(jù)庫的查詢語言,這就要求被查詢的數(shù)據(jù)只能位于數(shù)據(jù)庫中。但在實際工作中,時常會碰到一些不是來源于數(shù)據(jù)庫的數(shù)據(jù),特別是很多來自一些 Excel 表格或者 TXT 文本文件。如果要對它們進(jìn)行 SQL 查詢,通常做法是在數(shù)據(jù)庫中創(chuàng)建臨時表,然后導(dǎo)入數(shù)據(jù)后再使用 SQL 對其查詢。這種做法本身未嘗不可,但是有幾點不妥: 首先,比較麻煩,數(shù)據(jù)的來源五花八門,格式不同,表結(jié)構(gòu)也各不相同。導(dǎo)入操作往往只能由數(shù)據(jù)庫管理員手動維護(hù),其面臨的復(fù)雜度可想而知。 其次,數(shù)據(jù)庫常常會涉及敏感數(shù)據(jù)或安全考慮,就算你不怕麻煩,愿意去維護(hù),也未必有權(quán)限進(jìn)行這類操作。 最后,這些數(shù)據(jù)往往可能是臨時的、突發(fā)的,根本不適合往數(shù)據(jù)庫里添加,否則會搞得數(shù)據(jù)庫越來越臃腫,最終導(dǎo)致整體訪問性能低下。 有了這些不妥,程序員一般也就不得不放棄 SQL 式查詢了,只能通過程序?qū)崿F(xiàn)一些簡單的關(guān)鍵字搜索等功能,畢竟自己去實現(xiàn) SQL 語法的查詢不僅難度大而且完全沒必要。 但是 SQL 查詢有時候真的很好用啊……那么,有沒有一種第三方軟件能實現(xiàn) SQL 式查詢文本,讓程序員在享受便利的同時,不需要考慮上面這些煩心的問題呢? 答案自然是有,那就是本文要介紹的——集算器。 ? 開始 下面就來介紹一下,如何在 Java 中利用集算器實現(xiàn) SQL 式查詢文本文件。當(dāng)然,此處的文本文件不是指完全自由的文本文件,而是有格式規(guī)定的,類似于數(shù)據(jù)表的文件。 從官網(wǎng)下載并安裝好集算器,將 dm.jar 及其依賴的配置文件 raqsoftConfig.xml 加入到當(dāng)前程序的類路徑。然后使用集算器提供的 JDBC 類,便可將文本文件當(dāng)成數(shù)據(jù)庫中的數(shù)據(jù)表來進(jìn)行 SQL 式查詢了。 示例用到兩個文件,第一個 student.txt 數(shù)據(jù)內(nèi)容如下: 數(shù)據(jù)格式為:第一行為字段名,后續(xù)行是數(shù)據(jù),各列之間用 Tab 鍵分開。這個表是各個班級的學(xué)生基本情況。 第二個 score.txt 數(shù)據(jù)內(nèi)容如下: 這個文件通過‘班級’,‘學(xué)生 ID’兩個關(guān)鍵字段,記錄每個學(xué)生的各科成績。 ? JDBC 示例 對于熟悉 JDBC 的同學(xué)來說,Java 調(diào)用集算器使用 SQL 查詢文本的過程很簡單,下面貼出示例代碼: import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; public class SQLDemo { public static void main(String[] args) { Connection con = null;// 連接 Statement stmt = null;// 執(zhí)行語句 ResultSet rst = null;// 結(jié)果集 try { /********* 通過 JDBC 連接到 集算器 *********/ Class.forName(“com.esproc.jdbc.InternalDriver”); con = DriverManager.getConnection(“jdbc:esproc:local://”); /******************* 執(zhí)行語句方法 ********************/ stmt = con.createStatement(); rst = stmt.executeQuery(“SELECT * FROM score.txt”); /******************* 執(zhí)行語句方法結(jié)束 ****************/ ResultSetMetaData meta = rst.getMetaData(); for (int i = 0; i < meta.getColumnCount(); i++) { System.out.print(meta.getColumnName(i + 1) + “\t”); } System.out.println(); // 輸出結(jié)果 while (rst.next()) { for (int i = 0; i < meta.getColumnCount(); i++) { System.out.print(rst.getObject(i + 1) + “\t”); } System.out.println(); } stmt.close(); con.close(); } catch (ClassNotFoundException cnf) { System.out.println(“沒找到驅(qū)動程序”); cnf.printStackTrace(); } catch (SQLException se) { se.printStackTrace(); } } } 示例中可以看到加粗的 SQL 語句跟普通 SQL 語法基本一致,僅僅是表名不一樣,這里直接寫 TXT 文件名。執(zhí)行后結(jié)果如下: 可以看到,使用集算器的 JDBC,完全可以將具有表結(jié)構(gòu)的文本文件直接當(dāng)成數(shù)據(jù)表來查詢。而集算器除了支持 TXT 格式之外,還支持 CSV、XLS、XLSX 甚至 JSON。另外,集算器自身也有兩種數(shù)據(jù)存儲格式:BTX 和 CTX,也是可以直接查詢的。 好,進(jìn)一步的問題來了,集算器對 SQL 的各種命令能夠支持到何種程度呢? 首先需要說明的是,集算器不是一個數(shù)據(jù)庫產(chǎn)品,所以對 SQL 中一些數(shù)據(jù)庫維護(hù)命令是不支持的,比如 Create、Delete 等。 那么對于 Select 可以支持到什么程度呢? ? 分組統(tǒng)計 下面來看看 SQL 查詢中最普遍的查詢,將 student.txt 跟 score.txt 關(guān)聯(lián)起來,并分組統(tǒng)計出每名學(xué)生的總成績。將上面示例代碼中加粗的 SQL 語句替換為如下語句: SELECT A. 班級,A. 姓名,sum(B. 成績) 總分 FROM student.txt A JOIN score.txt B ON A. 班級 =B. 班級 AND A. 學(xué)生 ID=B. 學(xué)生 ID GROUP BY A. 班級,A. 姓名 執(zhí)行后,得到每班學(xué)生的總分表: 可以看到,集算器用 SQL 查詢文本時,對于常規(guī)的分組、表的聯(lián)合都沒問題。那么帶參數(shù)的查詢,又該如何寫呢? ? 使用參數(shù) 只需將執(zhí)行語句方法塊里的代碼替換為以下代碼: /******************* 執(zhí)行語句方法 ********************/ CallableStatement cs = null; // 定義 CallableStatement 對象 String String sql = “SELECT 姓名, 性別 FROM student.txt WHERE 班級 =?”; cs = con.prepareCall(sql); cs.setString(1, “一班”); rst = cs.executeQuery(); /******************* 執(zhí)行語句方法結(jié)束 ****************/ 換完后,注意要引入 CallableStatement 類。執(zhí)行后結(jié)果如下: 帶參數(shù)的句子仍然沒問題,調(diào)用方法也跟數(shù)據(jù)庫標(biāo)準(zhǔn)是一致的。不過上述結(jié)果中,性別顯示為數(shù)字,集算器 SQL 能不能支持轉(zhuǎn)換語法呢? ? CASE 語句 將上面的 SQL 語句替換成帶 CASE 的 SQL 語句: SELECT 姓名,CASE 性別 WHEN 0 THEN ‘男’ ELSE ‘女’ END 性別 FROM student.txt WHERE 班級 =? 結(jié)果如下: 通過上面這幾個例子可以看到,集算器對常用查詢的支持還是比較全面的。鑒于篇幅原因,這里就不繼續(xù)一一列舉了。更多集算器查詢文件時的詳細(xì)語法以及函數(shù),請參考文檔:http://doc./esproc/func/dbquerysql.html#db_sql_ |
|