Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Equals(=) vs. LIKE für Datumsdatentyp

Angenommen LAST_TRANSACTION_DATE ist ein DATE Spalte (oder TIMESTAMP ) dann sind beide Versionen sehr schlechte Praxis.

In beiden Fällen das DATE Spalte wird basierend auf den aktuellen NLS-Einstellungen implizit in ein Zeichenliteral konvertiert. Das bedeutet, dass Sie bei verschiedenen Clients unterschiedliche Ergebnisse erhalten.

Bei Verwendung von Datumsliteralen immer Verwenden Sie to_date() mit(!) einer Formatmaske oder verwenden Sie ein ANSI-Datumsliteral. Auf diese Weise vergleichen Sie Daten mit Daten und nicht Zeichenfolgen mit Zeichenfolgen. Für den gleichen Vergleich sollten Sie also verwenden:

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

Beachten Sie, dass die Verwendung von 'MON' bei unterschiedlichen NLS-Einstellungen immer noch zu Fehlern führen kann ('DEC' vs. 'DEZ' oder 'MAR' vs. 'MRZ' ). Die Verwendung von Monatszahlen (und vierstelligen Jahreszahlen) ist viel weniger fehleranfällig:

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

oder mit einem ANSI-Datumsliteral

LAST_TRANSACTION_DATE = DATE '2007-07-30'

Der Grund, warum die obige Abfrage sehr wahrscheinlich nichts zurückgibt, ist der in Oracle DATE Spalten enthalten auch die Uhrzeit. Die obigen Datumsliterale enthalten implizit die Uhrzeit 00:00 . Wenn die Uhrzeit in der Tabelle abweicht (z. B. 19:54 ) dann sind die Daten natürlich nicht gleich.

Um dieses Problem zu umgehen, haben Sie verschiedene Möglichkeiten:

  1. benutze trunc() in der Tabellenspalte, um die Uhrzeit auf 00:00 zu "normalisieren". trunc(LAST_TRANSACTION_DATE) = DATE '2007-07-30 dies verhindert jedoch die Verwendung eines am LAST_TRANSACTION_DATE definierten Index
  2. benutze 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')

Das Leistungsproblem der ersten Lösung könnte umgangen werden, indem ein Index auf trunc(LAST_TRANSACTION_DATE) erstellt wird die von diesem Ausdruck verwendet werden könnten. Aber der Ausdruck LAST_TRANSACTION_DATE = '30-JUL-07' verhindert auch eine Indexverwendung, da es intern als to_char(LAST_TRANSACTION_DATE) = '30-JUL-07' verarbeitet wird

Die wichtigsten Dinge, die Sie sich merken sollten:

  1. Verlassen Sie sich niemals auf die implizite Datentypkonvertierung. Es wird irgendwann Probleme machen. Vergleichen Sie immer die richtigen Datentypen
  2. Oracle DATE Spalten enthalten immer eine Zeit, die Teil der Vergleichsregeln ist.