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

Uguale (=) a LIKE per il tipo di dati della data

Assumendo LAST_TRANSACTION_DATE è una DATE colonna (o TIMESTAMP ) quindi entrambe le versioni sono pessime.

In entrambi i casi il DATE la colonna verrà convertita in modo implicito in un carattere letterale in base alle impostazioni NLS correnti. Ciò significa che con clienti diversi otterrai risultati diversi.

Quando si utilizzano i valori letterali della data sempre usa to_date() con (!) una maschera di formato o utilizzare una data letterale ANSI. In questo modo si confrontano le date con le date non le stringhe con le stringhe. Quindi per il confronto uguale dovresti usare:

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

Tieni presente che l'utilizzo di "MON" può comunque causare errori con impostazioni NLS diverse ('DEC' rispetto a 'DEZ' o 'MAR' rispetto a 'MRZ' ). È molto meno soggetto a errori utilizzando i numeri dei mesi (e gli anni a quattro cifre):

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

o utilizzando una data letterale ANSI

LAST_TRANSACTION_DATE = DATE '2007-07-30'

Ora il motivo per cui è molto probabile che la query sopra non restituisca nulla è che in Oracle DATE le colonne includono anche l'ora. I valori di data sopra riportati contengono implicitamente l'ora 00:00 . Se l'ora nella tabella è diversa (es. 19:54 ) quindi ovviamente le date non sono uguali.

Per aggirare questo problema hai diverse opzioni:

  1. usa trunc() nella colonna della tabella per "normalizzare" l'ora a 00:00 trunc(LAST_TRANSACTION_DATE) = DATE '2007-07-30 ciò impedirà comunque l'utilizzo di un indice definito il LAST_TRANSACTION_DATE
  2. usa 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')

Il problema delle prestazioni della prima soluzione potrebbe essere risolto creando un indice su trunc(LAST_TRANSACTION_DATE) che potrebbe essere utilizzato da tale espressione. Ma l'espressione LAST_TRANSACTION_DATE = '30-JUL-07' impedisce anche l'utilizzo di un indice perché internamente viene elaborato come to_char(LAST_TRANSACTION_DATE) = '30-JUL-07'

Le cose importanti da ricordare:

  1. Mai, mai fare affidamento sulla conversione implicita del tipo di dati. farà darti problemi ad un certo punto. Confronta sempre i tipi di dati corretti
  2. Oracle DATE le colonne contengono sempre un'ora che fa parte delle regole di confronto.