我有一个连接两个表的查询。一个表的列为varchar类型,另一个表的类型为number。我已经在3个oracle数据库上执行了我的查询,并且看到了一些我希望可以解释的奇怪结果。在两个数据库中,类似于以下工作。
select a.col1, b.somecol
from tableA a inner join tableB b on b.col2=a.col1;
在此查询中,tableA.col1的类型为number,tableB.col2的类型为varchar。这在两个数据库中工作正常,但在第三个数据库中没有。在第三个我得到(ORA-01722)错误。在第三个我需要做的事情......
select a.col1, b.somecol
from tableA a inner join tableB b on b.col2=to_char(a.col1);
这适用于所有数据库。我的问题是为什么?以上是一个简化的查询,真正的查询稍微复杂一点,并检索大量数据,因此第一个版本要快得多。如果我能让它在所有环境中工作那就太棒了。
有没有人知道为什么这可能在某些oracle数据库中有效而不是在没有数据类型强制转换的情况下有效?是否存在能够实现此类行为的全局设置?
答案 0 :(得分:17)
隐式转换失败的一个原因是连接varchar列包含非数字的数据。 Oracle通过转换字符串来处理数字到varchar2连接(在他的评论中查看Gary的引用),所以它实际上执行了这个:
select a.col1, b.somecol
from tableA a inner join tableB b on to_number(b.col2)=a.col1;
如果tableB.col2包含非数字的值 - 似乎很可能,它毕竟是一个字符串 - 然后它会向ORA-01722: invalid number
投掷。通过将数字列显式地转换为字符串,可以使Oracle的默认行为发生短路。
在前两个环境中没有遇到此问题的事实是运气而不是配置。它可以随时打击,因为它只需要一个非数字字符串来打破查询。所以你应该在所有环境中使用显式转换运行。
至于性能,您可以构建基于函数的索引......
create index whatever_idx on tableA ( to_char(col1) )
/