Forudsat LAST_TRANSACTION_DATE
er en DATE
kolonne (eller TIMESTAMP
) så er begge versioner meget dårlig praksis.
I begge tilfælde DATE
kolonne vil implicit blive konverteret til en bogstavelig karakter baseret på de aktuelle NLS-indstillinger. Det betyder, at du med forskellige kunder får forskellige resultater.
Når du bruger bogstaver for dato altid brug to_date()
med(!) en formatmaske eller brug en ANSI-dato. På den måde sammenligner du datoer med datoer og ikke strenge med strenge. Så for den lige sammenligning skal du bruge:
LAST_TRANSACTION_DATE = to_date('30-JUL-07', 'dd-mon-yy')
Bemærk, at brug af 'MON' stadig kan føre til fejl med forskellige NLS-indstillinger ('DEC'
vs. 'DEZ'
eller 'MAR'
vs. 'MRZ'
). Det er meget mindre fejltilbøjeligt ved at bruge månedstal (og firecifrede årstal):
LAST_TRANSACTION_DATE = to_date('30-07-2007', 'dd-mm-yyyy')
eller ved at bruge en ANSI-dato bogstavelig
LAST_TRANSACTION_DATE = DATE '2007-07-30'
Grunden til, at ovenstående forespørgsel med stor sandsynlighed ikke returnerer noget, er den i Oracle DATE
kolonner inkluderer også tiden. Ovenstående bogstaver for dato indeholder implicit tiden 00:00
. Hvis tiden i tabellen er anderledes (f.eks. 19:54
) så er datoerne selvfølgelig ikke ens.
For at løse dette problem har du forskellige muligheder:
- brug
trunc()
i tabelkolonnen for at "normalisere" tiden til00:00
trunc(LAST_TRANSACTION_DATE) = DATE '2007-07-30
dette vil dog forhindre brugen af et indeks defineret denLAST_TRANSACTION_DATE
- brug
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')
Ydeevneproblemet for den første løsning kunne løses ved at oprette et indeks på trunc(LAST_TRANSACTION_DATE)
som kunne bruges af det udtryk. Men udtrykket LAST_TRANSACTION_DATE = '30-JUL-07'
forhindrer også indeksbrug, fordi det internt behandles som to_char(LAST_TRANSACTION_DATE) = '30-JUL-07'
De vigtige ting at huske:
- Stol aldrig på implicit datatypekonvertering. Det vil give dig problemer på et tidspunkt. Sammenlign altid de korrekte datatyper
- Oracle
DATE
kolonner indeholder altid en tid, som er en del af sammenligningsreglerne.