2016-01-12 3 views
15

Я просто заметил любопытное поведение оракула TO_DATE функция при использовании с параметром format_mask.Oracle TO_DATE NOT throwing error

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

Пример 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

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

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

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

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

+0

Я взял на себя смелость запуска фрагментов и редактирование вопроса включить фактический вывод. Я думаю, что это может означать, что вы получаете «ORA-01843: недействительный месяц», а не «ORA-01830: конец формата даты заканчивается перед преобразованием всей строки ввода» или что-то еще. –

ответ

18

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

Он является частью правил преобразования раздела Стринг-To-Date модели формата 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; 

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

[Error] Исполнение (4: 16): ORA-01858: нечисловое персонаж нашел где ожидался числовой

В то время как следующие:

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

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

2/18/2016

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

+1

Точно, что мне нужно, спасибо. Кроме того, ответ был на странице, которую я связал в своем вопросе. О. Я действительно должен был прочитать это до конца. –

+1

Не беспокойтесь, это довольно небольшой раздел в конце большого документа. знак равно – gmiley

4

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

+0

Что это за «детерминированное представление даты» и как оно работает? Где я могу найти его описание? И что более важно - как я могу отключить его? Кроме того, если вы рассматриваете мой пример, вы можете видеть, что в обоих случаях Oracle имеет точно такую ​​же информацию, чтобы распознавать реальный формат, и в обоих случаях облако делает это правильно. –

+1

Вы выключаете его, когда указываете точную маску: «FX ». Я действительно работал с детерминизмом, потому что 'TO_DATE ('2016111', 'YYYYMMDD')' не детерминирован, я мог бы быть 2016-11-01 или 2016-01-11, а Oracle предпочитает первый элемент, поэтому это 2016-11-01 , – Husqvik

2

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

+0

Да, но 'SELECT TO_DATE ('feb-08-2016', 'DD/MM/YYYY') FROM dual' не работает, правильно? Я уточню свой вопрос, чтобы быть более конкретным. –

+0

Это дало ошибку, но 'SELECT TO_DATE ('feb-08-2016', 'MM/DD/YYYY') FROM dual;' did not. Так должно быть по дизайну – Utsav

2

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

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;