Oracle中的TO_NUMBER函数出现了奇怪的问题

Faz*_*zal 4 sql oracle oracle10g ora-01722

如果记录数超过某个数n,我在varchar2列的where子句中执行to_number函数时遇到了间歇性问题.我使用了n,因为它没有确切的记录数.在一个数据库上它发生在n为100万,而另一个数据库为0.1时.百万.

例如,我有一个包含1000万条记录的表,例如Table Country,其中field1 varchar2包含数字数据和Id

如果我以查询为例

select * 
from country 
where to_number(field1) = 23
and id >1 and id < 100000
Run Code Online (Sandbox Code Playgroud)

这有效

但是,如果我进行查询

select * 
from country 
where to_number(field1) = 23 
and id >1 and id < 100001
Run Code Online (Sandbox Code Playgroud)

它无法说出无效的号码

接下来我尝试查询

select * 
from country
where to_number(field1) = 23 
and id >2 and id < 100001
Run Code Online (Sandbox Code Playgroud)

它又有效了

由于我只得到无效的数字,这令人困惑,但在日志文件中它说

Memory Notification: Library Cache Object loaded into SGA
Heap size 3823K exceeds notification threshold (2048K)
KGL object name :with sqlplan as (
    select c006 object_owner, c007 object_type,c008 object_name
      from htmldb_collections
     where COLLECTION_NAME='HTMLDB_QUERY_PLAN'
       and c007 in ('TABLE','INDEX','MATERIALIZED VIEW','INDEX (UNIQUE)')),
ws_schemas as(
    select schema 
      from wwv_flow_company_schemas
     where security_group_id = :flow_security_group_id),
t as(
        select s.object_owner table_owner,s.object_name table_name,
               d.OBJECT_ID
          from sqlplan s,sys.dba_objects d
Run Code Online (Sandbox Code Playgroud)

它似乎与SGA大小有关,但谷歌没有给我很多帮助.

有没有人对TO_NUMBER或大数据的oracle函数有任何疑问?

APC*_*APC 5

其中field1 varchar2包含数字数据

这不是好习惯.数字数据应保留在NUMBER列中.原因很简单:如果我们不强制执行强数据类型,我们可能会在varchar2列中发现非数字数据.如果发生这种情况,那就是这样的过滤器

where to_number(field1) = 23 
Run Code Online (Sandbox Code Playgroud)

会失败的ORA-01722: invalid number.

我无法肯定地说这是你的场景中发生的事情,因为我不明白为什么ID过滤器中显然无关紧要的变化改变了查询的成功.查看不同版本查询的执行计划是有益的.但我认为,与SGA中的错误相比,您的数据更容易出现问题.

  • 查询中没有任何内容规定谓词的顺序.某些查询可能首先对id进行过滤,并且排除行时因为它们与to_number()不匹配,所以永远不会对该行进行求值.其他人可能会在id之前应用to_number(),同一行会产生错误. (4认同)
  • 值范围的大小可能导致优化器更改谓词的评估顺序; 在示例中,它超过了1%的数据,这听起来很低,但统计数据比实际行数更重要.因此,对于小范围,它可能会使用id上的索引,在大范围内它可能会忽略索引并执行完整扫描,在路上遇到无效数字varchar2值的to_number(),正如@Gary所说. (3认同)