Nå, jeg er i stand til at replikere det, og årsagen bag sådan adfærd er Oracles fortolkning af prædikater.
Version af OS og Oracle, hvor dette kan gengives:
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>
I det første tilfælde modificeres prædikatet til filter("D"."DT" IS NOT NULL)
mens prædikatet i den anden forespørgsel fungerer som angivet 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>
Jeg kunne ikke finde ud af denne adfærd hos Oracle, meget muligt kan nogle eksperter forklare dette.
Igen i det tredje eksempel bruges prædikater korrekt. 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>
Det er helt indlysende, at det samme ikke kan gengives fra Oracle Version 11.2.0.2.0 og 11.2.0.3.0 på Linux-servere.
Opdatering:
Som Alex Poole nævnt i kommentarerne - "Dette kan være fejl 9495697, 'Forkerte resultater kan returneres for en forespørgsel, der indeholder to OR'd-filterprædikater i samme kolonne, hvor den anden side af et prædikat ikke er en kompileringstidskonstant (f.eks. Det er en bind, sysdate osv..)"