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

Equals(=) vs. LIKE untuk tipe data tanggal

Dengan asumsi LAST_TRANSACTION_DATE adalah DATE kolom (atau TIMESTAMP ) maka kedua versi tersebut adalah praktik yang sangat buruk.

Dalam kedua kasus DATE kolom secara implisit akan dikonversi ke literal karakter berdasarkan pengaturan NLS saat ini. Itu berarti dengan klien yang berbeda Anda akan mendapatkan hasil yang berbeda.

Saat menggunakan literal tanggal selalu gunakan to_date() with(!) format mask atau gunakan ANSI date literal. Dengan begitu Anda membandingkan tanggal dengan tanggal bukan string dengan string. Jadi untuk perbandingan yang sama Anda harus menggunakan:

LAST_TRANSACTION_DATE = to_date('30-JUL-07', 'dd-mon-yy')

Perhatikan bahwa menggunakan 'MON' masih dapat menyebabkan kesalahan dengan setelan NLS yang berbeda ('DEC' vs. 'DEZ' atau 'MAR' vs. 'MRZ' ). Jauh lebih sedikit rawan kesalahan menggunakan nomor bulan (dan empat digit tahun):

LAST_TRANSACTION_DATE = to_date('30-07-2007', 'dd-mm-yyyy')

atau menggunakan literal tanggal ANSI

LAST_TRANSACTION_DATE = DATE '2007-07-30'

Sekarang alasan mengapa kueri di atas kemungkinan besar tidak menghasilkan apa-apa adalah karena di Oracle DATE kolom termasuk waktu juga. Literal tanggal di atas secara implisit berisi waktu 00:00 . Jika waktu dalam tabel berbeda (mis. 19:54 ) maka tentu saja tanggalnya tidak sama.

Untuk mengatasi masalah ini, Anda memiliki opsi berbeda:

  1. gunakan trunc() pada kolom tabel untuk "menormalkan" waktu ke 00:00 trunc(LAST_TRANSACTION_DATE) = DATE '2007-07-30 namun ini akan mencegah penggunaan indeks yang ditentukan pada LAST_TRANSACTION_DATE
  2. gunakan between
    LAST_TRANSACTION_DATE between to_date('2007-07-30 00:00:00', 'yyyy-mm-dd hh24:mi:ss') and to_date('2007-07-30 23:59:59', 'yyyy-mm-dd hh24:mi:ss')

Masalah kinerja dari solusi pertama dapat diatasi dengan membuat indeks pada trunc(LAST_TRANSACTION_DATE) yang dapat digunakan oleh ekspresi itu. Tapi ekspresi LAST_TRANSACTION_DATE = '30-JUL-07' mencegah penggunaan indeks juga karena secara internal diproses sebagai to_char(LAST_TRANSACTION_DATE) = '30-JUL-07'

Hal-hal penting untuk diingat:

  1. Jangan pernah mengandalkan konversi tipe data implisit. Itu akan memberi Anda masalah di beberapa titik. Selalu bandingkan tipe data yang benar
  2. Oracle DATE kolom selalu berisi waktu yang merupakan bagian dari aturan perbandingan.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bisakah Anda menggunakan Microsoft Entity Framework dengan Oracle?

  2. Oracle menyisipkan dari pilih ke dalam tabel dengan lebih banyak kolom

  3. Ubah VARCHAR2 menjadi Angka

  4. Menghubungkan C# ke Oracle

  5. Bagaimana saya bisa membuat klausa WHERE dinamis?