关闭

Oracle数据类型的隐性转换

发表于:2009-11-10 11:12

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:未知    来源:51Testing软件测试网采编

#
Oracle

 今天,以前开发的一个系统出问题,一句类似这样的sql语句:

  select * from t where a=1

  其中a是varchar类型。在测试机上跑得好好的,在生产机就报invalid number的错。原因涉及oracle数据库在解析sql语句的时候,对数据进行了类型转换,实际执行的是:

  select * from t where to_number(a)=1

  只要表t里面有一条记录的a字段含有不能转换为number的数字,就出错了,而错误当然就是invalid number了。

  此外,由于这样写语句要对表中a字段所有数据都做一次运算,什么索引都没用了,每次搜索都会进行全表扫描和运算,造成性能的下降。所以,就算不出错,也一定要根据数据类型写sql语句。如上例,写成这样就好了:

  select * from t where a='1'

  当然,因为这个系统比较小,业务简单,所以是用简单jsp实现的,所有sql语句都自己生成。如果大一点的系统,就可能会用到框架。如何优化对数据库的访问很大程度上都是框架的问题了。

  下面是网上搜索到的一篇关于oracle数据类型隐性转换的文章

  ORACLE数据类型的隐性转换

  出于优化的目的,在SQL 的编码中我们常提到要避免对字段进行计算,通常情况下字段的计算导致相应索引无法被使用,造成语句执行的开销增大,然而编码中稍有不慎,Oracle自动进行的隐性转换仍有可能进行了我们不希望看到的操作,进而带来严重的后果,索引扫描可能被替换为几千万行的全表扫描,甚至导致业务逻辑发生变化。因此本文列举了代码中常见的几种隐性类型转换,总结并论证其间的规律,以期在开发工作中避免其带来的危害。

  为举例创建一个表,包含隐性转换中常见的三种字段类型,并给每个字段建一个索引:

  *********************************************************

  create table TT2

  (

  NUMCOL     NUMBER, CHARCOL    CHAR(10),

  VARCHARCOL VARCHAR2(10)

  );

  create index IDX_CHAR on TT2 (CHARCOL);

  create index IDX_NUM on TT2 (NUMCOL);

  create index IDX_VARCHAR on TT2 (VARCHARCOL);

  insert into tt2 (numcol,charcol,varcharcol) values (1,'123','1');

  *********************************************************

  首先将varchar字段与number常量进行比较。

  *********************************************************

  SQL> select /*+ RULE*/ * from tt2 where varcharcol=1;

  NUMCOL CHARCOL VARCHARCOL

  ----------    ----------       ----------

  1 123 1

  Execution Plan

  ---------------------------------------------------------

  0 SELECT STATEMENT Optimizer=HINT: RULE

  1 0 TABLE ACCESS (FULL) OF 'TT2'

  这里我们加入了一个RULE 的提示,指定了RBO的优化方式,因此有索引的情况下理所当然优先使用索引,但是恰恰相反,执行计划选择了全表扫描,究其原因,乃是隐性地对 varchar2类型的字段进行了to_number的转换从而屏蔽了索引,实际的Where条件为to_number(varcharcol)=1

  变换一下,用number字段与字符常量比较。

  *********************************************************

  SQL> select /*+ RULE */ * from tt2 where numcol='1';

  NUMCOL CHARCOL VARCHARCOL

  ----------   ----------     ----------

  1 123 1

  Execution Plan

  ----------------------------------------------------------

  0 SELECT STATEMENT Optimizer=HINT: RULE

  1 0 TABLE ACCESS (BY INDEX ROWID) OF 'TT2'

  2 1 INDEX (RANGE SCAN) OF 'IDX_NUM' (NON-UNIQUE)

  *********************************************************

21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号