2014-01-12 48 views
1

與SYSDATE比較我剛剛創建了以下數據的樣本表:使用「或」在日期型列問題條款當甲骨文

CREATE TABLE AAA ( DT DATE ); 
insert into aaa (DT) values (to_date('13-01-2013', 'dd-mm-yyyy')); 
insert into aaa (DT) values (to_date('14-01-2013', 'dd-mm-yyyy')); 
insert into aaa (DT) values (to_date('15-01-2013', 'dd-mm-yyyy')); 
insert into aaa (DT) values (to_date('16-01-2013', 'dd-mm-yyyy')); 
insert into aaa (DT) values (to_date('17-01-2013', 'dd-mm-yyyy')); 
insert into aaa (DT) values (to_date('18-01-2013', 'dd-mm-yyyy')); 
insert into aaa (DT) values (to_date('19-01-2013', 'dd-mm-yyyy')); 
insert into aaa (DT) values (to_date('20-01-2013', 'dd-mm-yyyy')); 
insert into aaa (DT) values (to_date('21-01-2013', 'dd-mm-yyyy')); 
insert into aaa (DT) values (to_date('22-01-2013', 'dd-mm-yyyy')); 
insert into aaa (DT) values (to_date('23-01-2013', 'dd-mm-yyyy')); 
insert into aaa (DT) values (to_date('24-01-2013', 'dd-mm-yyyy')); 
insert into aaa (DT) values (to_date('25-01-2013', 'dd-mm-yyyy')); 
insert into aaa (DT) values (to_date('26-01-2013', 'dd-mm-yyyy')); 
insert into aaa (DT) values (to_date('27-01-2013', 'dd-mm-yyyy')); 

commit; 

,然後下面的查詢,返回結果異常: (15條記錄,而不是7)

select count(*) from aaa d 
where 
(d.dt > sysdate) 
or 
d.dt < to_date(20130120,'yyyymmdd') 

,但是當我改變左側和右側 「或」 返回正確的結果:(7條)

select count(*) from aaa d 
where 
d.dt < to_date(20130120,'yyyymmdd') 
or 
(d.dt > sysdate) 

有沒有人知道這個問題是什麼以及如何解決它?

加:與d.dt + 1更換d.dt也是解決這個問題,

d.dt+1 > sysdate+1 
+2

無法重現:http://sqlfiddle.com/#!4/f6dff/4 –

+0

'to_date()'需要一個字符,而不是一個數字。所以'to_date(20130120,'yyyymmdd')'無效。 –

+0

@a_horse_with_no_name - Oracle將應用隱式轉換,因此該語句有效。 – APC

回答

3

好吧,我能複製它,後面這種行爲的原因是謂詞的Oracle的解釋。

OS和Oracle的版本,其中這可以被再現:

SQL> host ver 

Microsoft Windows [Version 6.1.7601] 

SQL> select * from v$version; 

BANNER 
-------------------------------------------------------------------------------- 
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production 
PL/SQL Release 11.2.0.1.0 - Production 
CORE 11.2.0.1.0  Production 
TNS for 64-bit Windows: Version 11.2.0.1.0 - Production 
NLSRTL Version 11.2.0.1.0 - Production 

SQL> 

在第一種情況謂詞被修改爲filter("D"."DT" IS NOT NULL) 而在第二查詢中,謂詞所提供的工作原理filter("D"."DT"<TO_DATE(' 2013-01-20 00:00:00', 'syyyy-mm-dd hh24:mi:ss') OR "D"."DT">[email protected]!)

SQL> select count(*) 
    2 from aaa d 
    3 where (d.dt > sysdate) 
    4 or d.dt < to_date('20130120','yyyymmdd') 
    5/

    COUNT(*) 
---------- 
     15 

Execution Plan 
---------------------------------------------------------- 
Plan hash value: 977873394 

--------------------------------------------------------------------------- 
| Id | Operation   | Name | Rows | Bytes | Cost (%CPU)| Time  | 
--------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT |  |  1 |  9 |  3 (0)| 00:00:01 | 
| 1 | SORT AGGREGATE |  |  1 |  9 |   |   | 
|* 2 | TABLE ACCESS FULL| AAA | 15 | 135 |  3 (0)| 00:00:01 | 
--------------------------------------------------------------------------- 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

    2 - filter("D"."DT" IS NOT NULL) 

Note 
----- 
    - dynamic sampling used for this statement (level=2) 


Statistics 

---------------------------------------------------------- 
     4 recursive calls 
     0 db block gets 
    15 consistent gets 
     0 physical reads 
     0 redo size 
    346 bytes sent via SQL*Net to client 
    364 bytes received via SQL*Net from client 
     2 SQL*Net roundtrips to/from client 
     0 sorts (memory) 
     0 sorts (disk) 
     1 rows processed 

SQL> ed 
Wrote file afiedt.buf 

    1 select count(*) 
    2 from aaa d 
    3 where d.dt < to_date('20130120','yyyymmdd') 
    4* or (d.dt > sysdate) 
SQL> 
/

    COUNT(*) 
---------- 
     7 

Execution Plan 
---------------------------------------------------------- 
Plan hash value: 977873394 

--------------------------------------------------------------------------- 
| Id | Operation   | Name | Rows | Bytes | Cost (%CPU)| Time  | 
--------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT |  |  1 |  9 |  3 (0)| 00:00:01 | 
| 1 | SORT AGGREGATE |  |  1 |  9 |   |   | 
|* 2 | TABLE ACCESS FULL| AAA |  7 | 63 |  3 (0)| 00:00:01 | 
--------------------------------------------------------------------------- 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

    2 - filter("D"."DT"<TO_DATE(' 2013-01-20 00:00:00', 'syyyy-mm-dd 
       hh24:mi:ss') OR "D"."DT">[email protected]!) 

Note 
----- 
    - dynamic sampling used for this statement (level=2) 

Statistics 

---------------------------------------------------------- 
     4 recursive calls 
     0 db block gets 
    15 consistent gets 
     0 physical reads 
     0 redo size 
    346 bytes sent via SQL*Net to client 
    364 bytes received via SQL*Net from client 
     2 SQL*Net roundtrips to/from client 
     0 sorts (memory) 
     0 sorts (disk) 
     1 rows processed 

SQL> 

我無法弄清楚Oracle的這種行爲,很可能有些專家可以解釋這一點。

再次在第三個示例中,正確使用了謂詞。 filter("D"."DT"<TO_DATE(' 2013-01-20 00:00:00', 'syyyy-mm-dd hh24:mi:ss') OR INTERNAL_FUNCTION("D"."DT")+1>[email protected]!+1)

SQL> ed 
Wrote file afiedt.buf 

    1 select count(*) 
    2 from aaa d 
    3 where (d.dt + 1 > sysdate + 1) 
    4* or d.dt < to_date('20130120','yyyymmdd') 
SQL>/

    COUNT(*) 
---------- 
     7 

Execution Plan 
---------------------------------------------------------- 
Plan hash value: 977873394 

--------------------------------------------------------------------------- 
| Id | Operation   | Name | Rows | Bytes | Cost (%CPU)| Time  | 
--------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT |  |  1 |  9 |  3 (0)| 00:00:01 | 
| 1 | SORT AGGREGATE |  |  1 |  9 |   |   | 
|* 2 | TABLE ACCESS FULL| AAA |  7 | 63 |  3 (0)| 00:00:01 | 
--------------------------------------------------------------------------- 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

    2 - filter("D"."DT"<TO_DATE(' 2013-01-20 00:00:00', 'syyyy-mm-dd 
       hh24:mi:ss') OR INTERNAL_FUNCTION("D"."DT")+1>[email protected]!+1) 

Note 
----- 
    - dynamic sampling used for this statement (level=2) 


Statistics 
---------------------------------------------------------- 
      5 recursive calls 
      0 db block gets 
     15 consistent gets 
      0 physical reads 
      0 redo size 
     346 bytes sent via SQL*Net to client 
     364 bytes received via SQL*Net from client 
      2 SQL*Net roundtrips to/from client 
      0 sorts (memory) 
      0 sorts (disk) 
      1 rows processed 

SQL> 

它很明顯的是,不能從Oracle版本11.2.0.2.0和11.2.0.3.0在Linux服務器上覆制。

更新:

由於亞歷克斯·普爾在評論中提到 - 「這可能是錯誤9495697「,結果錯誤可能包含在同一列兩個邏輯過濾謂詞查詢返回的,其中一個謂詞的另一端不是編譯時常量(例如它是綁定,系統日期等)。「

+0

您可以使用哪個版本和補丁程序級別進行重現? –

+0

嗨,亞歷克斯,我轉載它在Oracle 11r2版本,安裝在Windows 7 64位體系結構。 – San

+0

11.2.0.1,還是補丁?它似乎在11.2.0.2(似乎正在運行SQL小提琴)或更高版本上不可重現。如果您處於更高版本的補丁級別,那麼它可能是特定於操作系統的。真的好奇,它似乎是一個錯誤。 –