`
xiaoyu1985ban
  • 浏览: 130096 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

JDBC中,如何快速的获取结果集结构?

阅读更多

问题描述:

对于给定的SQL语句(SELECT),以及数据库信息(url,用户名,密码),如何快速获取SQL语句执行后返回的结果集的结构?比如包含的字段个数,包含的字段名称以及Java类型

 

小试牛刀:

第一眼看上去,问题确实很简单。任何对JDBC有一定了解的人,都会很容易给出下面的方案:

1、根据数据库信息,创建数据库Connection;

2、利用Connection和SQL语句,创建一个PreparedStatement;

3、执行PreparedStatement,获取结果集ResultSet;

4、通过ResultSet获取ResultSetMetaData,所有的信息都在ResultSetMetaData中。

代码很快写好了,测试一下吧,select * from table,ok没问题。

 

问题出现了:

代码顺利提交,正寻思休息一下,测试姐姐满头大汗的过来了:

帮我看看,我的页面怎么死住了?

怎么可能?我测试可是没问题的啊。是不是你的SQL写的不对啊。

没有啊,我写的也是select * from table。

 

经过一番查找,终于发现问题了:

我的table里,只有100条数据,测试姐姐的表,居然有5,000,000条数据,select *一次,居然一分钟,IE长时间等不到返回,直接就死住了。

 

问题的症结:

其实上面的方案还是正确的,问题主要是查询出来的数据太多,导致数据库长时间不返回,页面就死掉了。

如果有一种方案,能保证查询出来的数据很少,最好是一条记录都没有,就好了。反正我要的是结果集的结构,不关心有没有数据。

将SQL修改成:select * from table where 1=2,用测试姐姐的数据表试试,页面马上就出来了,看来这招可行。

 

再次尝试:

经过上面的尝试,初步确定了第二个方案:对于用户给定的SQL,拼接上一个永假式,再执行拼接后的SQL。因为拼接了永假式,所以不会有满足条件的数据,这样就可以快速的获取到ResultSet了。

对于用户给定的SQL语句,可以采用以下方式处理:

1、直接拼接永假式,如:select * from table,拼接后:select * from table where 1=2

2、如果上面的方式不成立,再次尝试,如: select * from table t where t.id > 100,可以拼结成:select * from table t where t.id > 100 AND 1 = 2

3、如果第2种方式依然不行,直接执行SQL。

 

可惜,这种方案能依然存在问题:

1、最坏的情况下,需要查询三次数据库;

2、如果第3步查询的结果集中,包含数据过大,页面依然会假死。

 

最终解决:

吃午饭的时候,和DBA简单的聊了一会儿,到底是DBA,一句话点醒梦中人:用子查询。

 

最终得到了方案,很简洁:

对于用户输入的SQL,转化为以下形式:

       SELECT * FROM ( SQL )  TEST_SQL_TEMP WHERE 1 = 2

 

让我们进一步看一下: 

1、我们将SQL作为一个子查询,起了一个别名 TEST_SQL_TEMP ;

2、然后我们基于TEST_SQL_TEMP进行查询,用SELECT * 可以保证结果集与直接执行SQL得到的结果集结构相同;

3、最后别忘了的永假式 WHERE 1=2

 

 

 

声明:

文章来自于ITeye,欢迎访问我的博客:xiaoyu1985ban.iteye.com

ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。若作者同意转载,必须以超链接形式标明文章原始出处和作者。

2
1
分享到:
评论
11 楼 junsure 2014-03-02  
其实这个解决方案还是存在问题的,加入传进来的sql是多表联合查询,含有重复的列的话,是查不出表结构的,只有当传递的sql查询出的列没有重复的,才是正确的实现,具体更通用的实现是什么样子,我正在纠结中,如果哪位有好的解决方案的话,请联系我,谢谢!!!!
qq:544754473
10 楼 junsure 2014-03-02  
其实这个解决方案还是存在问题的,加入传进来的sql是多表联合查询,含有重复的列的话,是查不出表结构的,只有当传递的sql查询出的列没有重复的,才是正确的实现,具体更通用的实现是什么样子,我正在纠结中,如果哪位有好的解决方案的话,请联系我,谢谢!!!!
qq:544754473
9 楼 kesideyu1989 2013-08-22  
select * from ( select top 1 * from demo_employee_source) sqltemp where 1 = 2
8 楼 xiaoyu1985ban 2012-05-30  
kensunhu 写道
通过你的实践说明了我的主观判断出错了。
只要你证明这两条SQL执行耗时一样,就可以用子查询方案。
select * from ( select * from demo_employee_source) sqltemp where 1 = 2
select * from ude.demo_employee_source where 1 = 2



呵呵,没事儿。

真心的感谢你的回复,相信经过这一番讨论,以后进来的人就更清楚了。

希望你继续关注我的博客。
7 楼 kensunhu 2012-05-29  
通过你的实践说明了我的主观判断出错了。
只要你证明这两条SQL执行耗时一样,就可以用子查询方案。
select * from ( select * from demo_employee_source) sqltemp where 1 = 2
select * from ude.demo_employee_source where 1 = 2



6 楼 xiaoyu1985ban 2012-05-25  
kensunhu 写道
SELECT * FROM ( SQL )  TEST_SQL_TEMP WHERE 1 = 2
优点:不会有数据返回给调用程序,减少了数据返回给程序的时间。
缺点:先执行的SQL,若表数据量巨大,查询全表扫描,依然会耗时很多,前台页面调用依然会假死。楼主可以验证下哦。本人认为嵌套查询还是没解决问题。

建议最好的解决方案是判断用户输入的SQL产生如下执行SQL:
SQL where 1=2   或
SQL and 1=2



十分感谢您的回复。
1、您说的那种方案,我已经尝试过了,但最后没有采用这种方案,具体原因您可以看文中“再次尝试”部分的内容。
2、关于子查询和直接拼接SQL谁耗时少的问题,我刚刚进行了验证。结果是两个SQL的执行计划是一样的。下面是验证的过程,跟您分享一下:

数据库:Oracle 11g
数据量:300万;
用户输入SQL: select * from demo_employee_source
第一个SQL(采用子查询方案拼接): select * from ( select * from demo_employee_source) sqltemp where 1 = 2第二个SQL (采用判断用户输入的方式拼接): select * from ude.demo_employee_source where 1 = 2
验证方式:直接在PL/SQL中,查看两个方案生成的SQL。
验证结果:两个SQL的执行计划是一样的。
5 楼 kensunhu 2012-05-25  
SELECT * FROM ( SQL )  TEST_SQL_TEMP WHERE 1 = 2
优点:不会有数据返回给调用程序,减少了数据返回给程序的时间。
缺点:先执行的SQL,若表数据量巨大,查询全表扫描,依然会耗时很多,前台页面调用依然会假死。楼主可以验证下哦。本人认为嵌套查询还是没解决问题。

建议最好的解决方案是判断用户输入的SQL产生如下执行SQL:
SQL where 1=2   或
SQL and 1=2
4 楼 唔系好人 2012-05-24  
xiaoyu1985ban 写道
kensunhu 写道
请问下:
select * from ( select * from table_name) TEST_SQL_TEMP  where 1=2
若先执行select * from table_name查询的话,是否也会先把所有记录查出来呢?


很好的问题。

select * from table_name,在执行时,查询计划包括两个部分:

第一部分:TABLE ACCESS FULL 耗时:62290
第二部分:SELECT STATEMENT, GOAL = ALL_ROW,耗时 62290

select * from ( select * from table_name) TEST_SQL_TEMP  where 1=2  在执行时,查询计划包括三个部分:
第一部分:TABLE ACCESS FULL 耗时:62290
第二部分:Filter(WHERE条件)
第三部分:SELECT STATEMENT, GOAL = ALL_ROW,耗时 0

添加永假式的主要作用,是降低了SELECT STATEMENT部分的时间,但是TABLE ACCESS FULL这部分的时间,是不能省略的。


3 楼 xiaoyu1985ban 2012-05-23  
kensunhu 写道
请问下:
select * from ( select * from table_name) TEST_SQL_TEMP  where 1=2
若先执行select * from table_name查询的话,是否也会先把所有记录查出来呢?


很好的问题。

select * from table_name,在执行时,查询计划包括两个部分:

第一部分:TABLE ACCESS FULL 耗时:62290
第二部分:SELECT STATEMENT, GOAL = ALL_ROW,耗时 62290

select * from ( select * from table_name) TEST_SQL_TEMP  where 1=2  在执行时,查询计划包括三个部分:
第一部分:TABLE ACCESS FULL 耗时:62290
第二部分:Filter(WHERE条件)
第三部分:SELECT STATEMENT, GOAL = ALL_ROW,耗时 0

添加永假式的主要作用,是降低了SELECT STATEMENT部分的时间,但是TABLE ACCESS FULL这部分的时间,是不能省略的。

2 楼 kensunhu 2012-05-23  
请问下:
select * from ( select * from table_name) TEST_SQL_TEMP  where 1=2
若先执行select * from table_name查询的话,是否也会先把所有记录查出来呢?
1 楼 唔系好人 2012-05-22  

相关推荐

    Java Web编程宝典-十年典藏版.pdf.part2(共2个)

    《Java Web编程宝典(十年典藏版)》是一本集技能、范例、项目和应用为一体的学习手册,书中介绍了应用Java Web进行程序开发的各种技术、技巧。全书分4篇,共24章,其中,第1篇为技能学习篇,主要包括Java Web开发环境...

    Java开发实战1200例(第1卷).(清华出版.李钟尉.陈丹丹).part3

    实例239 结果集与Bean列表 301 实例240 编写MD5查看器 302 实例241 基于Base64编码 304 实例242 基于Base64解码 305 实例243 发送简单的Email 306 实例244 发送带附件的Email 308 实例245 读取XML文件属性 310 第3篇...

    MySQL 5.1中文手冊

    10.2. MySQL中的字符集和校对 10.3. 确定默认字符集和校对 10.3.1. 服务器字符集和校对 10.3.2. 数据库字符集和校对 10.3.3. 表字符集和校对 10.3.4. 列字符集和校对 10.3.5. 字符集和校对分配示例 10.3.6. 连接字符...

    mysql官方中文参考手册

    10.2. MySQL中的字符集和校对 10.3. 确定默认字符集和校对 10.3.1. 服务器字符集和校对 10.3.2. 数据库字符集和校对 10.3.3. 表字符集和校对 10.3.4. 列字符集和校对 10.3.5. 字符集和校对分配示例 10.3.6. 连接字符...

    Spring.3.x企业应用开发实战(完整版).part2

    此外,本书重点突出了“实战性”的主题,力求使全书“从实际项目中来,到实际项目中去”。 目录 第1篇 概述 第1章 Spring概述 1.1 认识Spring 1.2 关于SpringSource 1.3 Spring带给我们什么 1.4 Spring体系结构 1.5 ...

    Spring3.x企业应用开发实战(完整版) part1

    此外,本书重点突出了“实战性”的主题,力求使全书“从实际项目中来,到实际项目中去”。 目录 第1篇 概述 第1章 Spring概述 1.1 认识Spring 1.2 关于SpringSource 1.3 Spring带给我们什么 1.4 Spring体系结构 1.5 ...

    weixin135房屋租赁管理系统的设计与实现+ssm--论文pf.rar

    MyBatis:一个优秀的持久层框架,它支持自定义SQL、存储过程以及高级映射,并且避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。 数据库:通常使用MySQL或其他关系型数据库来存储数据,如用户信息、房产...

    MYSQL中文手册

    10.2. MySQL中的字符集和校对 10.3. 确定默认字符集和校对 10.3.1. 服务器字符集和校对 10.3.2. 数据库字符集和校对 10.3.3. 表字符集和校对 10.3.4. 列字符集和校对 10.3.5. 字符集和校对分配示例 10.3.6. ...

    MySQL 5.1参考手册

    10.2. MySQL中的字符集和校对 10.3. 确定默认字符集和校对 10.3.1. 服务器字符集和校对 10.3.2. 数据库字符集和校对 10.3.3. 表字符集和校对 10.3.4. 列字符集和校对 10.3.5. 字符集和校对分配示例 10.3.6. 连接字符...

    MySQL 5.1参考手册中文版

    10.2. MySQL中的字符集和校对 10.3. 确定默认字符集和校对 10.3.1. 服务器字符集和校对 10.3.2. 数据库字符集和校对 10.3.3. 表字符集和校对 10.3.4. 列字符集和校对 10.3.5. 字符集和校对分配示例 10.3.6. ...

    MySQL 5.1官方简体中文参考手册

    10.2. MySQL中的字符集和校对 10.3. 确定默认字符集和校对 10.3.1. 服务器字符集和校对 10.3.2. 数据库字符集和校对 10.3.3. 表字符集和校对 10.3.4. 列字符集和校对 10.3.5. 字符集和校对分配示例 10.3.6. 连接字符...

    MySQL 5.1参考手册 (中文版)

    10.2. MySQL中的字符集和校对 10.3. 确定默认字符集和校对 10.3.1. 服务器字符集和校对 10.3.2. 数据库字符集和校对 10.3.3. 表字符集和校对 10.3.4. 列字符集和校对 10.3.5. 字符集和校对分配示例 10.3.6. 连接字符...

    MySQL5.1参考手册官方简体中文版

    10.2. MySQL中的字符集和校对 10.3. 确定默认字符集和校对 10.3.1. 服务器字符集和校对 10.3.2. 数据库字符集和校对 10.3.3. 表字符集和校对 10.3.4. 列字符集和校对 10.3.5. 字符集和校对分配示例 10.3.6. 连接字符...

    Oracle SQL高级编程(资深Oracle专家力作,OakTable团队推荐)--随书源代码

    4.3.1 空值与非直观结果 108 4.3.2 集合运算中的空值行为 110 4.3.3 空值与GROUP BY和ORDER BY 112 4.3.4 空值与聚合函数 114 4.4 小结 114 第5章 关于问题 116 5.1 问出好的问题 116 5.2 提问的目的 117 ...

Global site tag (gtag.js) - Google Analytics