Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

menggunakan atau di mana klausa untuk masalah kolom tipe tanggal jika dibandingkan dengan sysdate di Oracle

Saya dapat menirunya dan alasan di balik perilaku tersebut adalah interpretasi Oracle terhadap predikat.

Versi OS dan Oracle tempat ini dapat direproduksi:

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>

Dalam kasus pertama, predikat diubah menjadi filter("D"."DT" IS NOT NULL) sementara di kueri kedua, predikat berfungsi seperti yang disediakan 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>

Saya tidak dapat memahami perilaku Oracle ini, sangat mungkin beberapa ahli dapat menjelaskan hal ini.

Sekali lagi dalam contoh ketiga, predikat digunakan dengan benar. 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>

Cukup jelas bahwa hal yang sama tidak dapat direproduksi dari Oracle Versi 11.2.0.2.0 dan 11.2.0.3.0 di server Linux.

Pembaruan:

Sebagai Alex Poole disebutkan dalam komentar - "Ini mungkin bug 9495697, 'Hasil yang salah dapat dikembalikan untuk kueri yang berisi dua predikat filter ATAU pada kolom yang sama, di mana sisi lain dari satu predikat bukan konstanta waktu kompilasi (mis. Ini adalah bind, sysdate, dll.)"




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cara Mendaftar Semua Prosedur Tersimpan di Database Oracle

  2. seperti apa indeks B-tree pada lebih dari 1 kolom?

  3. Menggunakan database Oracle dengan CakePHP 2.0

  4. Cara tercepat untuk mengidentifikasi perbedaan antara dua tabel?

  5. Jalankan dbms_mview.refresh dari CodeIgniter