Ошибка Oracle TO_DATE NOT throwing

Я просто заметил любопытное поведение оракула TO_DATE при использовании с format_mask.

В основном, я вижу, что в одном случае он игнорирует данную маску формата и анализирует ввод своей собственной маской, а в других случаях генерирует исключение.

Пример I ожидаемое поведение - ошибка брошена:

SELECT TO_DATE('18-02-2016', 'DD/MON/YYYY') FROM dual

ORA-01843: недействительный месяц

Пример II неожиданное поведение - дата проанализирована:

SELECT TO_DATE('18-feb-2016', 'DD/MM/YYYY') FROM dual

18 февраля 2016 00:00:00

Я не вижу никаких замечаний этого в документах, поэтому мне интересно, является ли это непоследовательность по дизайну или это ошибка, или, может быть, я не понимаю что-то правильное?

Edit: Глядя на ответы, я могу согласиться, что это, скорее всего, по дизайну. Но то, что делается здесь, выглядит опасно "автоматическим" для меня.

Что делать, если формат будет интерпретироваться (догадаться оракулом) неправильно? Есть ли какая-либо документация о том, что здесь происходит, поэтому я могу быть уверен, что это безопасно?

Мой вопрос будет тогда - я могу отключить его? Является ли мой единственный вариант проверки формата самостоятельно?

Ответы

Ответ 1

См. таблицу здесь: https://docs.oracle.com/cd/B28359_01/server.111/b28286/sql_elements004.htm#g195479

Это часть правила правил преобразования строк в дату модели формата Datetime. В случае MM, если нет совпадения, он пытается выполнить MON и MONTH. Аналогично, если вы укажете MON и не найдете этого, он попытается MONTH. Если вы укажете MONTH и он не сможет найти это, он попытается MON, но никогда не будет пытаться MM на что угодно, кроме MM.

В ответ на вопрос: Can I turn it off? Ответ: Да.

Вы можете сделать это, указав FX как часть вашего форматирования.

SELECT TO_DATE('18/february/2016', 'FXDD/MM/YYYY') FROM dual;

Теперь возвращается:

[Ошибка] Выполнение (4: 16): ORA-01858: нечисловой символ был где ожидалось число

Принимая во внимание следующее:

SELECT TO_DATE('18/02/2016', 'FXDD/MM/YYYY') FROM dual;

Возвращает ожидаемое:

2/18/2016

Обратите внимание, что при указании FX вы ДОЛЖНЫ использовать соответствующие разделители, иначе это будет ошибка.

Ответ 2

Это по дизайну. Oracle пытается найти детерминированное представление даты в строке, даже если не соответствует определенной маске. Он выдает ошибку только в том случае, если она не находит детерминированной даты или какой-либо необходимый компонент даты отсутствует или не разрешен.

Ответ 3

Я думаю, что 02 может означать дату/месяц/год, но feb будет означать только одно: a month. Также я перекрестно проверил то же самое в 11g и получил тот же результат, что и в 12c. Таким образом, имеет дизайн оракула. ​​

Ответ 4

Если вы хотите отключить попытку Oracle быть полезной и интерпретировать вещи, которые точно не совпадают, вы можете использовать модификатор формата FX:

FX
Формат точный. Этот модификатор определяет точное соответствие для модели символьного аргумента и модели формата даты и времени функции TO_DATE:

  • Пунктуация и цитируемый текст в аргументе символа должны точно соответствовать (за исключением случая) соответствующим частям модели формата.
  • Символьный аргумент не может иметь дополнительных пробелов. Без FX Oracle игнорирует дополнительные пробелы.
  • Числовые данные в аргументе символа должны иметь такое же количество цифр, что и соответствующий элемент в модели формата. Без FX числа в аргументе символа могут опускать начальные нули.
  • Когда FX включен, вы можете отключить эту проверку для ведущих нулей, используя также модификатор FM.

Итак, ваш пример будет ошибочным:

SELECT TO_DATE('18-feb-2016', 'FXDD/MM/YYYY') FROM dual;

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

Это также потребует, чтобы разделители соответствовали точно:

SELECT TO_DATE('18-02-2016', 'FXDD/MM/YYYY') FROM dual;

SQL Error: ORA-01861: literal does not match format string

Если вы это исправите, то это ОК:

SELECT TO_DATE('18/02/2016', 'FXDD/MM/YYYY') FROM dual;
SELECT TO_DATE('18-feb-2016', 'FXDD-MON-YYYY') FROM dual;

Он не жалуется на другой случай во втором примере. Но он будет жаловаться, если вы опустите ведущие нули;

SELECT TO_DATE('18/2/2016', 'FXDD/MM/YYYY') FROM dual;

SQL Error: ORA-01862: the numeric value does not match the length of the format item

... если вы также не включили модификатор FM:

SELECT TO_DATE('18/2/2016', 'FMFXDD/MM/YYYY') FROM dual;