Java 中如何使用 SQL 查询文本

【摘要】         

          使用 SQL 查询语言,你只能查询位于数据库里面的数据,但是当你面对的数据是一些 Excel 表格或者 Txt 文本格式时,有什么办法能直接对着文件进行 Select 查询呢?去乾学院看个究竟: Java 中如何使用 SQL 查询文本 !


Ø 引言

        作为一名数据库开发程序员,使用 SQL 语言查询数据是再普通不过的一件事。而 SQL 语言是基于数据库的查询语言,这就要求被查询的数据只能位于数据库中。但在实际工作中,时常会碰到一些不是来源于数据库的数据,特别是很多来自一些 Excel 表格或者 TXT 文本文件。如果要对它们进行 SQL 查询,通常做法是在数据库中创建临时表,然后导入数据后再使用 SQL 对其查询。这种做法本身未尝不可,但是有几点不妥:

        首先,比较麻烦,数据的来源五花八门,格式不同,表结构也各不相同。导入操作往往只能由数据库管理员手动维护,其面临的复杂度可想而知。

        其次,数据库常常会涉及敏感数据或安全考虑,就算你不怕麻烦,愿意去维护,也未必有权限进行这类操作。

        最后,这些数据往往可能是临时的、突发的,根本不适合往数据库里添加,否则会搞得数据库越来越臃肿,最终导致整体访问性能低下。

        有了这些不妥,程序员一般也就不得不放弃 SQL 式查询了,只能通过程序实现一些简单的关键字搜索等功能,毕竟自己去实现 SQL 语法的查询不仅难度大而且完全没必要。

        但是 SQL 查询有时候真的很好用啊……那么,有没有一种第三方软件能实现 SQL 式查询文本,让程序员在享受便利的同时,不需要考虑上面这些烦心的问题呢?

        答案自然是有,那就是本文要介绍的—— 集算器

Ø 开始

        下面就来介绍一下,如何在 Java 中利用集算器实现 SQL 式查询文本文件。当然,此处的文本文件不是指完全自由的文本文件,而是有格式规定的,类似于数据表的文件。

        从官网下载并安装好集算器,将 dm.jar 及其依赖的配置文件 raqsoftConfig.xml 加入到当前程序的类路径。然后使用集算器提供的 JDBC 类,便可将文本文件当成数据库中的数据表来进行 SQL 式查询了。

        示例用到两个文件,第一个 student.txt 数据内容如下:

1551109626165205.png

        数据格式为:第一行为字段名,后续行是数据,各列之间用 Tab 键分开。这个表是各个班级的学生基本情况。

        第二个 score.txt 数据内容如下:

1551109626189815.png

        这个文件通过‘班级’,‘学生 ID’两个关键字段,记录每个学生的各科成绩。

Ø JDBC 示例

        对于熟悉 JDBC 的同学来说,Java 调用集算器使用 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;// 执行语句

ResultSet rst = null;// 结果集

try {

/********* 通过 JDBC 连接到 集算器 *********/

Class.forName(“com.esproc.jdbc.InternalDriver”);

con = DriverManager.getConnection(“jdbc:esproc:local://”);

/******************* 执行语句方法 ********************/

stmt = con.createStatement();

rst = stmt.executeQuery(“ SELECT * FROM score.txt ”);

/******************* 执行语句方法结束 ****************/

ResultSetMetaData meta = rst.getMetaData();

for (int i = 0; i < meta.getColumnCount(); i++) {

System.out.print(meta.getColumnName(i + 1) + “\t”);

}

System.out.println();

// 输出结果

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(“没找到驱动程序”);

cnf.printStackTrace();

} catch (SQLException se) {

se.printStackTrace();

}

}

}

        示例中可以看到加粗的 SQL 语句跟普通 SQL 语法基本一致,仅仅是表名不一样,这里直接写 TXT 文件名。执行后结果如下:

1551109626876644.png

        可以看到,使用集算器的 JDBC,完全可以将具有表结构的文本文件直接当成数据表来查询。而集算器除了支持 TXT 格式之外,还支持 CSV、XLS、XLSX 甚至 JSON。另外,集算器自身也有两种数据存储格式:BTX 和 CTX,也是可以直接查询的。

        好,进一步的问题来了,集算器对 SQL 的各种命令能够支持到何种程度呢?

        首先需要说明的是,集算器不是一个数据库产品,所以对 SQL 中一些数据库维护命令是不支持的,比如 Create、Delete 等。

        那么对于 Select 可以支持到什么程度呢?

Ø 分组统计

        下面来看看 SQL 查询中最普遍的查询,将 student.txt 跟 score.txt 关联起来,并分组统计出每名学生的总成绩。将上面示例代码中加粗的 SQL 语句替换为如下语句:

SELECT A. 班级,A. 姓名,sum(B. 成绩) 总分 FROM student.txt A JOIN score.txt B ON A. 班级 =B. 班级 AND A. 学生 ID=B. 学生 ID GROUP BY A. 班级,A. 姓名

        执行后,得到每班学生的总分表:

1551109626518643.png

        可以看到,集算器用 SQL 查询文本时,对于常规的分组、表的联合都没问题。那么带参数的查询,又该如何写呢?

Ø 使用参数

        只需将执行语句方法块里的代码替换为以下代码:

/******************* 执行语句方法 ********************/

CallableStatement cs = null; // 定义 CallableStatement 对象 String

String sql = “ SELECT 姓名, 性别 FROM student.txt WHERE 班级 =? ”;

cs = con.prepareCall(sql);

cs.setString(1, “一班”);

rst = cs.executeQuery();

/******************* 执行语句方法结束 ****************/

        换完后,注意要引入 CallableStatement 类。执行后结果如下:

1551109626110164.png

        带参数的句子仍然没问题,调用方法也跟数据库标准是一致的。不过上述结果中,性别显示为数字,集算器 SQL 能不能支持转换语法呢?

Ø CASE 语句

        将上面的 SQL 语句替换成带 CASE 的 SQL 语句:

SELECT 姓名,CASE 性别 WHEN 0 THEN ‘男’ ELSE ‘女’ END 性别 FROM student.txt WHERE 班级 =?

        结果如下:

1551109627753435.png

        通过上面这几个例子可以看到,集算器对常用查询的支持还是比较全面的。鉴于篇幅原因,这里就不继续一一列举了。更多集算器查询文件时的详细语法以及函数,请参考文档: http://doc.raqsoft.com.cn/esproc/func/dbquerysql.html#db_sql_


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/31543054/viewspace-2636982/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/31543054/viewspace-2636982/

Java数据库查询结果的输出 摘自:北京海脉信息咨询有限公司   利用Java开发数据库应用时,经常需要在用户界面上显示查询结果。我们可以利用Vector、JTable、AbstractTableModel等三个类较好地解决这一问题。 类Vector:   定义如下: public class Vector extends AbstractList implements List , Cloneable , Serializable{…} 类JTable:   JTable组件是Swing组件比较复杂的小件,隶属于javax.swing包,它能以二维表的形式显示数据。类Jtable: 定义如下: public class JTable extends JComponent implements TableModelListener, Scrollable, TableColumnModelListener, ListSelectionListener, CellEditorListener, Accessible{…} 类AbstractTableModel:   定义如下: public abstract class AbstractTableModel extends Object implements TableModel, Serializable{…}   生成一个具体的TableModel作为AbstractTableMode的子类,至少必须实现下面三个方法: public int getRowCount(); public int getColumnCount(); public Object getValueAt(int row, int column);   我们可以建立一个简单二维表(5×5): TableModel dataModel = new AbstractTableModel() { public int getColumnCount() { return 5; } public int getRowCount() { return 5;} public Object getValueAt(int row, int col) { return new Integer(row*col); } }; JTable table = new JTable(dataModel); JScrollPane scrollpane = new JScrollPane(table); 数据库及其连接方法:   我们采用Sybase数据库数据库存放在数据库服务器。路径为:D:WORKER,数据库名为:worker.dbf。具有以下字段: 字段名 类型 Wno(职工号) VARCHAR Wname(职工名) VARCHAR Sex(性别) VARCHAR Birthday(出生日期) DATE Wage(工资) FLOAT   要连接此数据库,需使用java.sql的类DriverManager。此类是用于管理JDBC驱动程序的实用程序类。它提供了通过驱动程序取得连接、注册,撤消驱动程序,设置登记和数据库访问登录超时等方法。   具体连接方法如下:   定位、装入和链接SybDriver类。 driver="com.sybase.jdbc.SybDriver"; SybDriver sybdriver=(SybDriver) Class.forName(driver).newInstance();   注册SybDriver类。 DriverManager.registerDriver(sybdriver);   取得连接(SybConnection)对象引用。 user="sa"; password=""; url="jdbc:sybase:Tds:202.117.203.114:5000/WORKER"; SybConnection connection= (SybConnection)DriverManager.getConnection (url,user,password); 建立完连接后,即可通过Statement接口进行数据库查询与更改。 实现方法:   对象声明。   AbstractTableModel tm;   //声明一个类AbstractTableModel对象   JTable jg_table;//声明一个类JTable对象   Vector vect;//声明一个向量对象   JScrollPane jsp;//声明一个滚动杠对象   String title[]={"职工号","职工名",   "性别","出生日期","工资"};   //二维表列名   定制表格。   实现抽象类AbstractTableModel对象tm的方法:   vect=new Vector();//实例化向量   tm=new AbstractTableModel(){   public int getColumnCount(){   return title.length;}//取得表格列数   public int getRowCount(){   return vect.size();}//取得表格行数   public Object getValueAt(int row,int column){   if(!vect.isEmpty())   return   ((Vector)vect.elementAt(row)).elementAt(column);   else   return null;}//取得单元格的属性值   public String getColumnName(int column){   return title[column];}//设置表格列名   public void setValueAt   (Object value,int row,int column){}   //数据模型不可编辑,该方法设置为空   public Class getColumnClass(int c){   return getValueAt(0,c).getClass();   }//取得列所属对象类   public boolean isCellEditable(int row,int column){   return false;}//设置单元格不可编辑,为缺省实现   };   定制表格:   jg_table=new JTable(tm);//生成自己的数据模型   jg_table.setToolTipText("显示全部查询结果");   //设置帮助提示   jg_table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);   //设置表格调整尺寸模式   jg_table.setCellSelectionEnabled(false);   //设置单元格选择方式   jg_table.setShowVerticalLines(true);//   设置是否显示单元格间的分割线   jg_table.setShowHorizontalLines(true);   jsp=new JScrollPane(jg_table);//给表格加上滚动杠   显示查询结果。   连接数据库:已给出。   数据库查询:   Statement stmt=connection.createStatement();   ResultSet rs=stmt.executeQuery   ("select * from worker");   显示查询结果:   vect.removeAllElements();//初始化向量对象   tm.fireTableStructureChanged();//更新表格内容   while(rs.next()){   Vector rec_vector=new Vector();   //从结果集取数据放入向量rec_vector   rec_vector.addElement(rs.getString(1));   rec_vector.addElement(rs.getString(2)); rec_vector.addElement(rs.getString(3)); rec_vector.addElement(rs.getDate(4));   rec_vector.addElement(new Float(rs.getFloat(5)));   vect.addElement(rec_vector);   //向量rec_vector加入向量vect   }   tm.fireTableStructureChanged();   //更新表格,显示向量vect的内容   实现示图记录前翻、后翻的效果,有两种方法:   如果软件环境支持JDBC2.0,可直接利用rs.prevoius()和rs.next()获得记录,然后通过类JTextField的setText()方法,显示出各个字段值。   如果不支持JDBC2.0,则可利用向量Vector按行取出JTable数据。自定义一个指针,用来记录位置。当指针加1时,取出上一行数据放入Vector显示;指针减1时,取出下一行数据显示。显示方法同上。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值