Приемаме LAST_TRANSACTION_DATE
е DATE
колона (или TIMESTAMP
) тогава и двете версии са много лоша практика.
И в двата случая DATE
колоната ще бъде имплицитно преобразувана в символен литерал въз основа на текущите настройки на NLS. Това означава, че с различни клиенти ще получите различни резултати.
Когато използвате литерали за дата винаги използвайте to_date()
с(!) маска на формат или използвайте ANSI литерал за дата. По този начин сравнявате дати с дати, а не низове с низове. Така че за еднакво сравнение трябва да използвате:
LAST_TRANSACTION_DATE = to_date('30-JUL-07', 'dd-mon-yy')
Имайте предвид, че използването на „MON“ все още може да доведе до грешки с различни NLS настройки ('DEC'
спрямо 'DEZ'
или 'MAR'
спрямо 'MRZ'
). Много по-малко е податливо на грешки при използване на номера на месеци (и четирицифрени години):
LAST_TRANSACTION_DATE = to_date('30-07-2007', 'dd-mm-yyyy')
или с помощта на ANSI литерал за дата
LAST_TRANSACTION_DATE = DATE '2007-07-30'
Сега причината, поради която горната заявка е много вероятно да не върне нищо, е, че в Oracle DATE
колоните включват и времето. Горните литерали за дата имплицитно съдържат часа 00:00
. Ако времето в таблицата е различно (напр. 19:54
) тогава, разбира се, датите не са равни.
За да заобиколите този проблем, имате различни опции:
- използвайте
trunc()
в колоната на таблицата, за да "нормализирате" времето до00:00
trunc(LAST_TRANSACTION_DATE) = DATE '2007-07-30
това обаче ще предотврати използването на индекс, дефиниран наLAST_TRANSACTION_DATE
- използвайте
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')
Проблемът с производителността на първото решение може да бъде заобиколен чрез създаване на индекс на trunc(LAST_TRANSACTION_DATE)
който може да се използва от този израз. Но изразът LAST_TRANSACTION_DATE = '30-JUL-07'
предотвратява и използването на индекс, тъй като вътрешно се обработва като to_char(LAST_TRANSACTION_DATE) = '30-JUL-07'
Важните неща, които трябва да запомните:
- Никога, никога не разчитайте на имплицитно преобразуване на тип данни. Това ще ви създава проблеми в даден момент. Винаги сравнявайте правилните типове данни
- Oracle
DATE
колоните винаги съдържат време, което е част от правилата за сравнение.