2011-09-07 65 views
12
SELECT COUNT (*) 
    FROM rps2_workflow 
WHERE  workflow_added > TO_DATE ('01.09.2011', 'dd.mm.yyyy') 
     AND workflow_finished < TO_DATE ('wtf', 'dd.mm.yyyy') 
     AND workflow_status IN (7, 12, 17) 
     AND workflow_worker = 159 

我希望此查询失败,因为无效的日期,但它返回0意外查询成功

此查询的计划显示,在8步无效条款处理:

8 TABLE ACCESS BY INDEX ROWID TABLE RPS2.RPS2_WORKFLOW Object Instance: 1 Filter Predicates: ("WORKFLOW_STATUS"=7 OR "WORKFLOW_STATUS"=12 OR "WORKFLOW_STATUS"=17) AND SYS_EXTRACT_UTC("WORKFLOW_FINISHED")<SYS_EXTRACT_UTC(TO_DATE('wtf','dd.mm.yyyy')) Cost: 11 Bytes: 33 Cardinality: 1 CPU Cost: 8 M IO Cost: 10 Time: 1      

如果我们注释掉AND workflow_status IN (7, 12, 17)条件 - 然后果然,我们得到ORA-01858: a non-numeric character was found where a numeric was expected

如果我们注释掉AND workflow_finished < TO_DATE ('wtf', 'dd.mm.yyyy')然后我们得到适合该条件的记录量(> 0)

这怎么可能?

UPD

如果优化决定其并不需要的提示/*+no_index(rps2_workflow) */不会改变任何东西(而在计划,我们看到全扫描进行)

SELECT STATEMENT ALL_ROWSCost: 254 Bytes: 31 Cardinality: 1 CPU Cost: 34 M IO Cost: 248 Time: 4  
2 SORT AGGREGATE Bytes: 31 Cardinality: 1  
    1 TABLE ACCESS FULL TABLE RPS2.RPS2_WORKFLOW Object Instance: 1 Filter Predicates: "WORKFLOW_WORKER"=159 AND ("WORKFLOW_STATUS"=7 OR "WORKFLOW_STATUS"=12 OR "WORKFLOW_STATUS"=17) AND SYS_EXTRACT_UTC("WORKFLOW_ADDED")>SYS_EXTRACT_UTC(TIMESTAMP' 2011-09-01 00:00:00') AND SYS_EXTRACT_UTC("WORKFLOW_FINISHED")<SYS_EXTRACT_UTC(TO_DATE('wtf','dd.mm.yyyy')) Cost: 254 Bytes: 31 Cardinality: 1 CPU Cost: 34 M IO Cost: 248 Time: 4 
+0

@BoltClock:aw,不能把sql放在标签列表的末尾:-S问题是oracle特有的,不只是一个普通的sql问题 – zerkms

+0

我猜想优化器发现没有记录(使用索引)工作者159状态为7,12或17,所以它没有打算评估其余的查询。当您删除状态检查时,会发现一些记录,因此需要评估TO_DATE功能并导致错误。很难说肯定查询优化器在做什么,但... – Sparky

+0

@Sparky:看看最后一段 - 如果我们删除“错误”的查询片段 - 它会返回行。我也是这么想的,但**有**指定状态的记录 – zerkms

回答

3

它可能发现,每满足所有其他条件记录有NULLworkflow_finished场。

NULL相比,任何事情都是未知的,所以它不需要评估其他操作数。

+1

+1只是一个小点:任何与NULL相比的东西都是未知的,不是假的,尽管它没有任何区别这里。 –

7

评估功能,它不会,所以功能永远不会抛出异常:

select 1 from dual where 1 = 1 OR to_date('asdasdasd','asdasdasdas') > sysdate ; 

     1 
---------- 
     1 

该函数引发只有当它实际上被评估的异常:

SQL> select 1 from dual where 1 = 1 AND to_date('asdasd','asdas') > sysdate ; 
select 1 from dual where 1 = 1 AND to_date('asdasd','asdas') > sysdate 
                * 
ERROR at line 1: 
ORA-01821: date format not recognized 

但是,如果解析器可以决定静态查询是无效的 - 因为该函数具有错误类型的参数或查询有无效的类型,那么优化器在它得到一个前摆解析器会引发异常:

SQL> select 1 from dual where 1 = 1 or to_date('asdasdasd',0) > sysdate ; 
select 1 from dual where 1 = 1 or to_date('asdasdasd',0) > sysdate 
                 * 
ERROR at line 1: 
ORA-00932: inconsistent datatypes: expected DATE got NUMBER 


SQL> select 1 from dual where 1 = 1 or to_date('asdasdasd','asdasdasdas') > 42 ; 
select 1 from dual where 1 = 1 or to_date('asdasdasd','asdasdasdas') > 42 
                     * 
ERROR at line 1: 
ORA-00932: inconsistent datatypes: expected DATE got NUMBER 
+0

即使你绝对正确 - 这不是一个答案。因为问题稍微深一点(不是谓词级别,而是操作数级别)。 alexisdm已经猜对了。 +1无论如何 – zerkms

+0

啊,我没有通读所有的“阅读更多”评论之前回答:) –

+0

但无论如何,你做了很好的工作。这些信息绝对会对任何其他读者有用。如果alexisdm没有提供他的答案 - 我会检查你的(并且会增加引起这种“奇怪”行为的情况) – zerkms