Het punt is dus dat Oracle-tijdstempels en Oracle-datums twee verschillende datatypes zijn. Om een tijdstempel te vergelijken met een datum moet Oracle een conversie uitvoeren - die INTERNAL_FUNCTION(). De interessante ontwerpbeslissing is dat Oracle de tabelkolom converteert in plaats van de doorgegeven waarde, wat betekent dat de query niet langer de index gebruikt.
Ik heb je scenario kunnen reproduceren in SQL*Plus, dus het is geen probleem om java.sql.Timestamp
te gebruiken . Het casten van de doorgegeven tijdstempels naar datums lost het probleem op...
SQL> explain plan for
2 select * from test1
3 where d1 > cast(to_timestamp('01-MAY-2011 00:00:00.000', 'DD-MON-YYYY Hh24:MI:SS.FF') as date)
4 and d2 > cast(to_timestamp('01-JUN-2011 23:59:59.999', 'DD-MON-YYYY Hh24:MI:SS.FF') as date)
5 /
Explained.
SQL> select * from table(dbms_xplan.display)
2 /
PLAN_TABLE_OUTPUT
-----------------------------------------------------------
Plan hash value: 1531258174
-------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 25 | 500 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| TEST1 | 25 | 500 | 3 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | T1_I | 1 | | 2 (0)| 00:00:01 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------
2 - access("D1">CAST(TO_TIMESTAMP('01-MAY-2011 00:00:00.000','DD-MON-YYYY
Hh24:MI:SS.FF') AS date) AND "D2">CAST(TO_TIMESTAMP('01-JUN-2011
23:59:59.999','DD-MON-YYYY Hh24:MI:SS.FF') AS date) AND "D1" IS NOT NULL)
filter("D2">CAST(TO_TIMESTAMP('01-JUN-2011 23:59:59.999','DD-MON-YYYY
Hh24:MI:SS.FF') AS date))
18 rows selected.
SQL>
Maar ik denk niet dat je daar iets aan hebt:het zou gemakkelijker zijn om in plaats daarvan gewoon datums door te geven.
Interessant is dat het niet helpt om een op functies gebaseerde index te bouwen die de datumkolommen cast naar tijdstempels. De INTERNAL_FUNCTION()
oproep wordt niet herkend als een CAST()
en de index wordt genegeerd. Een index proberen te bouwen met INTERNAL_FUNCTION()
gooit een ORA-00904.