Недействительный месяц - работа с датами в Oracle - PullRequest
0 голосов
/ 04 марта 2020

Мне тяжело работать с датами в моей индивидуальной среде. У меня есть запрос на добавление предложения where для указания c дат, но я просто не могу получить oracle в бюджет. Любые идеи, кто-нибудь пожалуйста.

 select created_date, cast(created_date as date) as created_date_cast
   from mytable;

 created_date                                  created_date_cast
 04-Mar-20 05.21.15.772000 AM                  3/4/2020 5:21:15 AM
 04-Mar-20 05.21.15.709000 AM                  3/4/2020 5:21:15 AM
 04-Mar-20 05.17.14.902000 AM                  3/4/2020 5:14:14 AM
 28-Feb-20 01.15.25.702700 AM                  2/28/2020 1:15:25 AM

Когда я пытаюсь добавить предложение where, фрагмент взрывается с ошибкой:

select created_date, cast(created_date as date) as created_date_cast
  from mytable
 where cast(created_date as date) <= '02/28/2020';

ORA-01843: not a valid month

Я также пытался to_date(created_date, 'MM/DD/YYYY') в из, но оказывается ошибочным с:

ORA-01858: a non-numeric character was found where a numeric was expected

Ответы [ 3 ]

1 голос
/ 04 марта 2020

Сначала приводится как дата, которая преобразует значение метки времени в значение даты, а затем не забудьте добавить функцию trunc(), чтобы включить значение dry boun (в данном случае date'2020-02-28') также как

where trunc(cast(created_date as date)) <= date'2020-02-28'

Демо

1 голос
/ 04 марта 2020

Не используйте 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 у вас было).

Вы никогда не должны полагаться на неявные преобразования строк, поскольку любой пользователь может изменить свои собственные параметры сеанса в любое время, и неявное преобразование, которое работает для одного пользователя, может не работать для другого только потому, что они имеют разные значения параметров (даже если запросы идентичны).

0 голосов
/ 04 марта 2020

Используйте литерал даты:

cast(created_date as date) <= date '2020-02-28'

Я бы также рекомендовал отказаться от cast() - при условии, что created_date правильно хранится как date или timestamp:

created_date < (date '2020-02-28' + interval '1' day)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...