隐式转换带来的麻烦
来源:互联网 发布:知行劳务 编辑:程序博客网 时间:2024/06/05 16:41
oracle的隐式转换有时候会给我们带来很隐蔽的麻烦。看一个简单的例子:
SQL>create table t1(val varchar2(10));Table created.SQL>insert into t1 values('XXX');1 row created.SQL>insert into t1 values('100');1 row created.SQL>commit;Commit complete.SQL>select * from t1 where val=100 and rownum<2;select * from t1 where val=100 and rownum<2 *ERROR at line 1:ORA-01722: invalid number
再看另一个例子:
SQL>create table t2(val varchar2(10));Table created.SQL>insert into t2 values('100');1 row created.SQL>insert into t2 values('XXX');1 row created.SQL>commit;Commit complete.SQL>select * from t2 where val=100 and rownum<2;VAL----------100
查询成功了。仔细观察两个例子,唯一的不同仅仅是两条数据的插入顺序不一样。数据库理论告诉我们,元组(行)在关系(表)中是没有顺序的,我们的程序不应当也不能依赖行的存储顺序。为什么这里会导致不同的结果呢?原因在于val字段类型是varchar2,在和数字100做比较的时候,oracle自动把val转换成了to_number(val)。两个例子都是全表扫描,对t1表,oracle首先读到的第一条记录是‘XXX',to_number自然就失败了,对t2表,oracle读到的第一条记录是'100',to_number成功且条件匹配,由于rownum条件只读取一条,所以立刻退出了,没发生任何错误。如果去掉rownum条件,则两个例子都失败。当然,如果oracle不转换val,而是把100转换成to_char(100),那就没问题了,但oracle认为数字比较总是比字符串比较效率高,所以优先将字符串类型转换为数字类型。
这不仅仅发生在表,索引上同样也会发生类似的情况。所以在设计数据库结构的时候,一定不要为了方便用varchar2去替代其他数据类型,否则一条错误数据就可能让程序崩溃。
查询oracle自己提供的视图也会碰到类似的情况,典型例子就是v$parameter,其中的value字段类型是varchar2,但存储的值有时候是需要转换成数字来进行相应计算的。一个常见的场景是direct path read/write 事件,如果是对TEMP文件进行读写,我们需要这样来获取文件名称:(假设事件P1值是201)
select a.name from v$tempfile a, v$parameter b where b.name='db_files' and a.file# + b.value = 201;
上面的sql是从《Oracle Wait Interface: A Practical Guide to Performance Diagnositics & Tuning》这本书里摘录的,在我的环境下(11.2.0.1.0),得到的唯一结果是ORA-01722。绕过去的办法是改变一下写法:
select a.name from v$tempfile a, v$parameter b where b.name='db_files' and a.file# = 201 - b.value ;
这样能查询到正确结果。但这样做仅仅是通过运气(如果有兴趣可以仔细研究一下两条语句不同的执行计划),正确的做法应该是始终保证比较类型的一致:
select a.name from v$tempfile a, v$parameter b where b.name='db_files' and b.value = to_char( 201 - a.file# ) ;
这样的话就能保证无论什么情况下都能得到正确结果。
- 隐式转换带来的麻烦
- 编写高质量代码——提防隐式转换带来的麻烦
- 改善C++ 程序的150个建议学习之建议17:提防隐式转换带来的麻烦
- DirectX9带来的麻烦
- 内码带来的麻烦
- StrPCopy带来的麻烦
- switch带来的麻烦
- DontDestroyOnLoad带来的麻烦
- 丢失钱包带来的麻烦
- 3322.org带来的麻烦
- WebBrowser多线程带来的麻烦
- WebBrowser多线程带来的麻烦 .
- c++ 隐式转换带来的问题
- C++隐式转换带来的问题
- UTF-8 的BOM带来的麻烦
- UTF-8 的BOM带来的麻烦
- UTF-8 的BOM带来的麻烦
- [笔记点]ONINIT带来的麻烦
- 3.1 什么是内核对象
- hdu2544
- 功能点(Funciton Point FP)估算法(三) 调整因子
- GCD的异步处理
- win7上部署aspx网站
- 隐式转换带来的麻烦
- 关于linux操作系统下的互斥量的建立
- 多态
- MyBatis入门示例——MyBatis学习笔记之一
- 功能点(Funciton Point FP)估算法(四) 功能点估算法
- 管式超滤系统工艺在饮水净化中作用详解
- C++ 虚函数表解析
- 当我拨开眼前寂寥的渔樵耕读 残碑是岁月磨平的书
- 查询大于100M的文件