#sql #oracle #date #timestamp #substr
Вопрос:
У меня есть поле типа данных varchar2 ( lmp_date
), которое может возвращать null
либо то, что выглядит как значение, либо то, что выглядит как timestamp
значение. Изменить базу data_type
данных на DATE
невозможно, поэтому теперь мне нужно преобразовать ее в дату, но со значениями, возвращаемыми этим столбцом, у меня возникли некоторые проблемы.
Возвращаемые значения для lmp_date
= null
или 2021-06-11-00.00.00
Необходим формат даты: MM/DD/YYYY
Я пытался cast
convert
, substr instr
но безрезультатно
ETA — Пара примеров попыток (потому что было 10 :
select order_no, to_date(lmp_date) lmp_date from table_a
— с сообщением об ошибке «ORA-01861: литерал не соответствует строке формата»
select order_no, to_date(substr(lmp_date, 1, instr(lmp_date, '00' -15))) lmp_date from table_a
— поскольку lmp_date
у null
него есть возможности для создания ценности, это не работает успешно
select order_no, cast(lmp_date as date) lmp_date from table_a
— с тем же сообщением об ошибке «ORA-01861: литерал не соответствует строке формата»
select order_no, to_date(lmp_date, 'YYYY-MM-DD') lmp_date from table_a
— ORA-01830: изображение в формате даты заканчивается перед преобразованием всей входной строки
Было больше попыток, это все, что я могу вспомнить
Комментарии:
1. Я предлагаю, что вам нужен тип данных даты, который не имеет присущего формата. Можете ли вы показать, как вы пытались выполнить преобразование?
2. Преобразование строки в дату выполняется
to_date()
; но, как уже было сказано, она не имеет удобочитаемого формата, поэтому вам нужно сохранить ее как дату или отформатировать обратно в строку?3. «Изменение типа data_type базы данных на СЕГОДНЯШНИЙ день невозможно» — это было бы единственным правильным решением.
Ответ №1:
Чтобы преобразовать строку в дату, используйте to_date()
функцию с подходящей маской формата:
to_date(lmp_date, 'YYYY-MM-DD-HH24:MI:SS')
Элементы модели формата приведены в документации.
Результатом этого является тип данных даты, который представляет собой внутреннее 7-байтовое представление. Ваш клиент или приложение отформатируют это для отображения, что может основываться на ваших настройках NLS_DATE_FORMAT, поэтому вы можете изменить их, чтобы изменить отображение всех дат; или использовать to_char()
для преобразования даты обратно в строку, например:
to_char(to_date(lmp_date, 'YYYY-MM-DD-HH24:MI:SS'), 'MM/DD/YYYY')
хотя, если вы хотите, чтобы это была та строка, вы можете просто использовать манипуляции со строками substr()
и объединение:
case when lmp_date is not null then
substr(lmp_date, 6, 2) || '/' || substr(lmp_date, 9, 2) || '/' || substr(lmp_date, 1, 4)
end
Когда вы делаете что-либо из этого:
to_date(lmp_date)
cast(lmp_date as date)
это также зависит от вашего сеанса NLS_DATE_FORMAT; и ошибка «литерал не соответствует строке формата» указывает на то, что он не соответствует строке, например, если у вас по-прежнему установлен параметр «DD-MON-RR» по умолчанию. Это действительно сработало бы — для вас в вашей текущей сессии — если бы вы изменили эту настройку. Я показал это здесь только для информации. но чтобы работать с кем угодно, независимо от настроек сеанса, вы должны использовать to_date()
явную маску формата и не полагаться и не предполагать ничего, относящегося к конкретному сеансу.
Ты был почти там с:
to_date(lmp_date, 'YYYY-MM-DD')
и снова сообщение «изображение формата даты заканчивается до преобразования всей входной строки» сообщает вам, что не так — ваша строка проходит мимо элементов ГГГГ-ММ-ДД. Расширение маски формата для соответствия всей строке, как я сделал выше, означает, что она знает, что означает каждая часть.
Если бы вас действительно интересовала только часть даты, вы могли бы отрезать конец строки:
to_date(substr(lmp_date, 1, 10), 'YYYY-MM-DD')
но это действительно полезно только в том случае, если у вас есть сочетание строковых значений, где у некоторых есть время, а у некоторых нет. (В результирующей дате всегда будет указано время; это будет просто полночь.) И если у вас есть даты в разных форматах, то это становится немного сложнее — отчасти поэтому вы не должны хранить даты в виде строк.
Комментарии:
1. Ваши начальные функции to_date(), to_char() и substr() работали до некоторой степени, пока я не попытался вытащить их и использовать для вычислений. Я могу получить данные для возврата со всем запросом, даже с вычислением даты, но если я попытаюсь сохранить их в нашем приложении, я получу ошибку «выражение SQL неверно». Если я попытаюсь экспортировать данные из окна SQL, при использовании функции to_date() я получу ошибку «ORA-01843: недопустимый месяц», а если я использую функцию substr (), я получу «ORA-01858: нечисловой символ был найден там, где ожидалось числовое значение» ошибка
2. Если вы скопируете и вставите из окна результатов, вы снова вернетесь к строковому значению, отформатированному с помощью NLS_DATE_FORMAT. Зависит от того, что вы подразумеваете под «экспортом», и какой это инструмент/среда разработки. «Выражение SQL неверно» не является ошибкой Oracle, поэтому ваше приложение или какой-либо фреймворк, похоже, говорят об этом, но я не могу предположить, почему. Вероятно, вам следует задать новый вопрос, показывающий, что именно делает ваше приложение и как оно пытается выполнить запрос, а также полную ошибку, которую оно получает.