2016-12-12 41 views
4

很久以前,在远处的一个数据库中,开发人员编写了一个查询,其中他/她依赖于写入谓词的顺序。Oracle 12c嵌入式视图评估

例如,

select x 
    from a, b 
where NOT REGEXP_LIKE (a.column, '[^[:digit:]]') 
    and a.char_column = b.numeric_column; 

(说明计划提出一个to_number转换将适用于a.char_column

我认为机会大于设计这个 “只是工程”(的Oracle 11g)。但是,在Oracle 12c中运行时谓词的顺序并未遵守,因此此查询会因无效的数字异常而中断。我知道,我可以尝试使用ORDERED_PREDICATES提示强制12C评估谓词以如下

select /*+ ORDERED_PREDICATES +*/ x 
    from a, b 
where NOT REGEXP_LIKE (a.column, '[^[:digit:]]') 
    and a.char_column = b.numeric_column 

..或投用to_char用于比较的值之一。缺点是to_char可能在一百万行上运行。我认为以下内联视图可能是更好的解决方案。我保证内嵌视图将首先被评估?

select x 
    from b 
    inner join (
       select only_rows_with_numeric_values as numeric_column 
       from a 
       where NOT REGEXP_LIKE (a.column, '[^[:digit:]]') 
      ) c 
    on c.numeric_column = b.numeric_column; 
+0

你说在b表上可能有数百万行('缺点是to_char可能会操作说一百万行');一个表中有多少行,因为会因为发生隐式转换而将to_number函数应用于该表中?如果表中有相似(或更多)的行数,那么由于to_char,您可能会看到对性能没有负面影响。 – Boneist

+1

或者,您可以在表a上创建一个仅包含数值的虚拟列(也可以索引该列),然后您的查询可以简化为'从a.new_numeric_virtual_column = b.numeric_column的内连接b中选择x; ' – Boneist

+0

现在,这是一个想法!我不得不承认我没有考虑虚拟专栏!感谢您的建议! – 0909EM

回答

1

关于预测顺序 - 看https://jonathanlewis.wordpress.com/2015/06/02/predicate-order-2/

您应该在最后一个查询重写然后根据DOC(https://docs.oracle.com/database/121/SQLRF/queries008.htm#SQLRF52358

select x 
    from b 
    inner join (
       select only_rows_with_numeric_values as numeric_column, 
       rownum 
       from a 
       where NOT REGEXP_LIKE (a.column, '[^[:digit:]]') 
      ) c 
    on c.numeric_column = b.numeric_column; 

压制查询unnesting或简单地使用提示/*+ no_unnest*/使用rownum

+0

感谢您的链接乔纳森刘易斯!在我的谷歌搜索中,我确实看到了rownum提到但在Oracle文档中看不到它,谢谢你的链接。 – 0909EM