Не используйте CAST
и не используйте TRUNC
(так как тогда Oracle не сможет использовать индекс для вашего столбца, но вместо этого потребует индекс на основе функций, созданный в TRUNC(created_date)
) просто добавьте день и используйте литерал:
SELECT created_date
FROM mytable
WHERE created_date < DATE '2020-02-29';
или
SELECT created_date
FROM mytable
WHERE created_date < TIMESTAMP '2020-02-29 00:00:00';
или, если вы хотите указать точную дату, просто добавьте день. Например:
SELECT created_date
FROM mytable
WHERE created_date < DATE '2020-02-28' + INTERVAL '1' DAY;
Все эти опции должны иметь возможность использовать индекс для столбца created_date
.
Я также пробовал to_date(created_date, 'MM/DD/YYYY')
в от, но доказывает, быть ошибочным с:
ORA-01858: a non-numeric character was found where a numeric was expected
TO_DATE( value_string, format_model )
принимает строки в качестве аргументов, но CREATED_DATE
является типом данных TIMESTAMP
, а не строкой, поэтому Oracle должен сделать неявным TIMESTAMP
преобразование в строку, и это делается с помощью параметра сеанса NLS_TIMESTAMP_FORMAT
; таким образом, ваше выражение эффективно:
TO_DATE(
TO_CHAR(
created_date,
( SELECT value FROM NLS_SESSION_PARAMETERS WHERE parameter = 'NLS_TIMESTAMP_FORMAT' )
),
'MM/DD/YYYY'
)
И если ваш NLS_TIMESTAMP_FORMAT
не MM/DD/YYYY
, то весьма вероятно, что будет сгенерировано исключение (то есть, как у ORA-01858
у вас было).
Вы никогда не должны полагаться на неявные преобразования строк, поскольку любой пользователь может изменить свои собственные параметры сеанса в любое время, и неявное преобразование, которое работает для одного пользователя, может не работать для другого только потому, что они имеют разные значения параметров (даже если запросы идентичны).