#sql #oracle #datetime
#sql #Oracle #дата-время
Вопрос:
У меня есть таблица oracle, которая содержит дату в формате дд-мм-гггг и дд / мм / гггг в том же поле. Теперь мне нужно преобразовать в один общий формат. Пожалуйста, предложите, как подойти к этому?
Я пытался, но он терпит неудачу, поскольку он терпит неудачу из-за недопустимого месяца. Есть ли способ, которым я могу сначала определить, в каком формате указана дата, а затем на основе заявления case, которое я мог бы преобразовать. или что-то простое? Пожалуйста
Комментарии:
1. Вы уверены, что у вас нет значений в
mm-dd-yyyy
формате? Вы не получите ошибку из-за разных символов-разделителей (если вы не принудите точное совпадение, используя модельFX
формата при преобразовании), поэтому ошибка, скорее всего, где-то в другом месте, и попытка указать месяц13
даст вамORA-01843: not a valid month
. Если у вас есть даты в обоихDD-MM-YYYY
MM-DD-YYYY
форматах и, тогда у вас БОЛЬШИЕ проблемы, поскольку вы не можете знать,01-02-2020
1 февраля или 2 января.
Ответ №1:
Я надеюсь, вы усвоили свой урок, и теперь вы собираетесь сохранить эти даты в типе данных date.
Ваши два разных формата даты на самом деле не важны, Oracle уже немного перестарался, когда дело доходит до разделения символов. например
to_date('01/01/1900','dd-mm-yyyy')
Не выдает ошибок
Я пытался, но он терпит неудачу, поскольку он терпит неудачу из-за недопустимого месяца.
Ваша ошибка возникает, потому что вы допустили значение, которое не соответствует ни одному из этих форматов в вашем столбце string.
Если у вас как минимум версия 12.2 (которая должна быть в 2020 году), вы можете использовать validate_conversion
функцию для идентификации строк, которые не преобразуются в дату в вашем формате (https://docs.oracle.com/en/database/oracle/oracle-database/12.2/sqlrf/VALIDATE_CONVERSION.html#GUID-DC485EEB-CB6D-42EF-97AA-4487884CB2CD)
select string_column
from my_table
where validate_conversion(string_column AS DATE,'dd/mm/yyyy') = 0
Другим дополнительным помощником, который мы получили в 12.2, было on conversion error
предложение to_date
. Так что вы можете сделать.
alter table my_table add my_date date;
update my_table set my_date = to_date(my_string default null on conversion error,'dd/mm/yyyy');
Комментарии:
1. Да, я усвоил урок, чтобы не иметь поля varchar для хранения данных даты и времени, но существующую проблему необходимо решить. Спасибо за ценные коды, буду работать над этим. Мне также понравилась идея, предложенная @GMB, заменить ‘/’ на ‘-‘ . Спасибо Эндрю Сэйеру
2. Как я указал в своем ответе, путаница / и — на самом деле не является проблемой для Oracle. Обе версии могут быть успешно преобразованы в дату с любым разделителем. Ваша проблема в том, что данные — это что-то другое — вероятно, когда дни и месяцы переворачиваются, поскольку он жалуется, что не может преобразовать их в месяц. Если это так, то на самом деле, вероятно, некоторые данные были сохранены неправильно, но все еще технически действительны (01/02/2020 может быть февраль или январь), это будет невозможно очистить без дополнительной информации о строке.
Ответ №2:
Если вы уверены, что не существует другого формата, кроме этих двух, простой подход replace()
:
update mytable set mystring = replace(mystring, '/', '-');
Это преобразует все даты в формат dd-mm-yyyy
.
Я бы предложил сделать шаг вперед и преобразовать эти строки в date
столбец.
alter table mytable add mydate date;
update mytable set mydate = to_date(replace(mystring, '/', '-'), 'dd-mm-yyyy');
Это приведет к сбою, если будут выполнены недопустимые строки даты. Я склонен считать это хорошей вещью, поскольку это ясно сигнализирует о том, что это проблема с данными. Если вы хотите избежать этого, вы можете использовать on conversion error
, доступный начиная с Oracle 12:
to_date(
replace(mystring, '/', '-') default null on conversion error,
'dd-mm-yyyy'
)
Затем вы можете удалить столбец string, который больше не нужен.
Комментарии:
1. Спасибо @GMB, за эту потрясающую идею … это выглядит выполнимым, поскольку столбец, который у меня есть, имеет varchar, поэтому я могу легко использовать функцию replace. И позже может быть преобразована в поле дата-время. Попробую этот подход, надеюсь, это сработает.