Oracle
 sql >> Database >  >> RDS >> Oracle

using o in where clausola per il problema della colonna del tipo di data quando confronta con sysdate in Oracle

Bene, sono in grado di replicarlo e il motivo alla base di tale comportamento è l'interpretazione dei predicati di Oracle.

Versione di OS e Oracle dove questo può essere riprodotto:

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>

Nel primo caso il predicato viene modificato in filter("D"."DT" IS NOT NULL) mentre nella seconda query, il predicato funziona come previsto 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>

Non sono riuscito a capire questo comportamento di Oracle, è possibile che alcuni esperti possano spiegarlo.

Anche nel terzo esempio, i predicati sono usati correttamente. 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>

È abbastanza ovvio che lo stesso non può essere riprodotto da Oracle Version 11.2.0.2.0 e 11.2.0.3.0 su server Linux.

Aggiornamento:

Come Alex Poole menzionato nei commenti - "Questo potrebbe essere un bug 9495697, 'Risultati errati possono essere restituiti per una query contenente due predicati di filtro OR sulla stessa colonna, dove l'altro lato di un predicato non è una costante in fase di compilazione (ad es. È un bind, sysdate, ecc.)"