JAVA的JDBC,对于取出的来结果集好象不能直接取到结果集的数量,要使用一个计数器,不停的next(),一直到结束。这样才得到数量。
这样的效率对于大量记录而言显然是不能忍受的。显然使用select count(*) from tableName可以获得最好的效率。那么,当有查询语句时,如何能方便、快捷的得到统计语句呢?这个需要在WEB项目上分页显示数据记录的时候用得比较多。
最近用了几次正则表达式,让我想到一个办法,可以使用正则表达式动态的根据查询SQL语句,自动的将形如select name,sex from tableName的查询SQL语句转换成select count(*) from tableName这样的统计SQL语句。大家知道,正则表达式有查找、替换功能,这正是完成这样任务所需要的。
做这样一个小任务的时候,先要理解正则表达式的贪心模式(也有叫贪婪模式)与非贪婪模式。
所谓贪婪模式,就是对于这样的SQL查询语句:
select name from (select name from tableName)
当使用正则表达式:(^select)(.*)( from .*) 进行匹配时,中间的(.*)部分,
在贪心模式
下,中间部分会尽可能多的匹配,其结果就是: name from (select name
在非贪心模式
下,中间部分会尽可能少的匹配,其结果就是: name
显然对于我的小任务而言,需要的是非贪心模式,那么如何让正则表达式切换到非贪心模式下呢?很简单,正则表达式写成这样就可以了:(^select)(.*?)( from .*)。这样就达到了预定的目的。
完整的java函数如下:
public String getCountSql(String sql) {
String regex = "(^select)(.*?)( from .*)";
Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(sql);
boolean rs = m.find();
if (rs == false || m.groupCount() != 3) {
return "";
} else
return m.group(1) + " count(*) " + m.group(3);
}
后记
这个小小的函数,有个BUG,不知大家想到没有,就是处理这样的SQL语句会有问题:
select (select max(id) from tableName)+1 id, name from tableName,
这时应该用到括号的匹配来去除干扰,不过正则表达式该怎么写,我还没有想出来,欢迎知道的朋友留言告知。
/***********本人原创,欢迎转载,转载请保留本人信息*************/
作者:wallimn 电邮:[email protected]:2009-02-13
博客:http://blog.csdn.net/wallimn http://wallimn.iteye.com
网络硬盘:http://wallimn.ys168.com
/***********文章发表请与本人联系,作者保留所有权利*************/
1 楼 CodingMouse 2010-01-03
我觉得没有必要搞得这么复杂,利用标准SQL组装一下即可。我是这样做的:
/**
* 执行查询SQL命令并返回数据库表记录统计行数。<br><br>
*
* @param sql 要执行的带占位符SQL命令字串。
* @param param SQL参数对象(无SQL参数时请使用 null 关键字)。
* @return 数据库表记录统计行数。
* @throws DataAccessException 数据访问异常。
*/
public int executeRowCount(
String sql,
SQLParameter param)
throws DataAccessException {
String newSql = "SELECT COUNT(*) QUERY_ROW_COUNT FROM ("
+ sql
+ ") CUSTOM_IMPORT_QUERY";
return Integer.valueOf(this.executeScalar(newSql, param).toString());
}
如果你有更好的方法,烦请电邮一份给我,谢谢!Email:[email protected]
/**
* 执行查询SQL命令并返回数据库表记录统计行数。<br><br>
*
* @param sql 要执行的带占位符SQL命令字串。
* @param param SQL参数对象(无SQL参数时请使用 null 关键字)。
* @return 数据库表记录统计行数。
* @throws DataAccessException 数据访问异常。
*/
public int executeRowCount(
String sql,
SQLParameter param)
throws DataAccessException {
String newSql = "SELECT COUNT(*) QUERY_ROW_COUNT FROM ("
+ sql
+ ") CUSTOM_IMPORT_QUERY";
return Integer.valueOf(this.executeScalar(newSql, param).toString());
}
如果你有更好的方法,烦请电邮一份给我,谢谢!Email:[email protected]
2 楼 CodingMouse 2010-01-03
忘了贴 executeScalar 方法了:
/**
* 执行查询SQL命令并返回单个值。<br><br>
*
* @param sql 要执行的带占位符SQL命令字串。
* @param param SQL参数对象(无SQL参数时请使用 null 关键字)。
* @return 单个值。
* @throws DataAccessException 数据访问异常。
*/
public Object executeScalar(
String sql,
SQLParameter param)
throws DataAccessException {
try {
this.conn = DB_CONNECTION_POOL.getConnection();
this.trans = new DBTransaction(this.conn);
this.trans.begin();
this.ps = DataTypeConverter.java2Jdbc(
this.conn.prepareStatement(sql),
param);
this.rs = this.ps.executeQuery();
Object value = null;
if (this.rs.next()) {
value = this.rs.getObject(1);
}
this.trans.commit();
return value;
} catch (Throwable e) {
this.trans.rollback();
throw new DataAccessException(e);
} finally {
this.closeAll();
}
}
如果你有更好的方法,烦请电邮一份给我,谢谢!Email:[email protected]
/**
* 执行查询SQL命令并返回单个值。<br><br>
*
* @param sql 要执行的带占位符SQL命令字串。
* @param param SQL参数对象(无SQL参数时请使用 null 关键字)。
* @return 单个值。
* @throws DataAccessException 数据访问异常。
*/
public Object executeScalar(
String sql,
SQLParameter param)
throws DataAccessException {
try {
this.conn = DB_CONNECTION_POOL.getConnection();
this.trans = new DBTransaction(this.conn);
this.trans.begin();
this.ps = DataTypeConverter.java2Jdbc(
this.conn.prepareStatement(sql),
param);
this.rs = this.ps.executeQuery();
Object value = null;
if (this.rs.next()) {
value = this.rs.getObject(1);
}
this.trans.commit();
return value;
} catch (Throwable e) {
this.trans.rollback();
throw new DataAccessException(e);
} finally {
this.closeAll();
}
}
如果你有更好的方法,烦请电邮一份给我,谢谢!Email:[email protected]