Oracle
 sql >> Base de données >  >> RDS >> Oracle

Equals(=) vs. LIKE pour le type de données de date

En supposant LAST_TRANSACTION_DATE est une DATE colonne (ou TIMESTAMP ) alors les deux versions sont de très mauvaises pratiques.

Dans les deux cas, la DATE colonne sera implicitement convertie en un littéral de caractère basé sur les paramètres NLS actuels. Cela signifie qu'avec différents clients, vous obtiendrez des résultats différents.

Lors de l'utilisation de littéraux de date toujours utilisez to_date() avec (!) un masque de format ou utilisez un littéral de date ANSI. De cette façon, vous comparez des dates avec des dates et non des chaînes avec des chaînes. Donc, pour la comparaison égale, vous devez utiliser :

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

Notez que l'utilisation de 'MON' peut toujours entraîner des erreurs avec différents paramètres NLS ('DEC' vs 'DEZ' ou 'MAR' vs 'MRZ' ). Il est beaucoup moins sujet aux erreurs en utilisant des nombres de mois (et des années à quatre chiffres) :

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

ou en utilisant un littéral de date ANSI

LAST_TRANSACTION_DATE = DATE '2007-07-30'

Maintenant, la raison pour laquelle la requête ci-dessus est très susceptible de ne rien renvoyer est que dans Oracle DATE les colonnes incluent également l'heure. Les littéraux de date ci-dessus contiennent implicitement l'heure 00:00 . Si l'heure indiquée dans le tableau est différente (par exemple, 19:54 ) alors bien sûr les dates ne sont pas égales.

Pour contourner ce problème, vous disposez de différentes options :

  1. utiliser trunc() sur la colonne du tableau pour "normaliser" l'heure à 00:00 trunc(LAST_TRANSACTION_DATE) = DATE '2007-07-30 cela empêchera cependant l'utilisation d'un index défini le LAST_TRANSACTION_DATE
  2. utiliser 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')

Le problème de performances de la première solution pourrait être contourné en créant un index sur trunc(LAST_TRANSACTION_DATE) qui pourrait être utilisé par cette expression. Mais l'expression LAST_TRANSACTION_DATE = '30-JUL-07' empêche également l'utilisation d'un index car il est traité en interne comme to_char(LAST_TRANSACTION_DATE) = '30-JUL-07'

Les choses importantes à retenir :

  1. Ne vous fiez jamais, au grand jamais, à la conversion implicite des types de données. Cela va vous donner des problèmes à un moment donné. Comparez toujours les bons types de données
  2. Oracle DATE les colonnes contiennent toujours une heure qui fait partie des règles de comparaison.