Ошибка при использовании to_date с указанием ORA-01722: неверный номер - PullRequest
0 голосов
/ 11 февраля 2020

Я пытаюсь собрать два поля, чтобы создать поле даты в мм / дд / гггг, используя case-when, и оно продолжает выдавать ошибку ORA-01722: недопустимое число.

case when 
  extract(month from t.date) >= t.month 
  then to_date(t.month || '/' || '01' || '/' || extract(year from t.date), 'mm/dd/yyyy')
  else to_date(t.month || '/' || '01' || '/' || extract(year from t.date)-1, 'mm/dd/yyyy')
  end as effective_date

Ответы [ 2 ]

0 голосов
/ 11 февраля 2020

Прежде всего, решение, предоставленное @ AP C, необходимо и достаточно для решения проблемы, представленной OP. Однако есть альтернатива, особенно. так как я сожалею о манипуляции со строками для дат. Преобразуйте строку в дату и с этого момента выполняйте ВСЕ дальнейшую обработку с использованием функций даты (или отметки времени, если необходимо). Нет НИКАКОЙ причины конвертировать дату в строку, за исключением окончательного отображения или экспорта. Поэтому я предлагаю следующую альтернативу для последующих зрителей. Представленная проблема сводится к следующему: Учитывая дату и целевой месяц - если месяц с датой совпадает с указанным месяцем позже, верните первый из целевого месяца. - если месяц даты предшествует целевому месяцу, верните первое целевого месяца в предыдущем году.

alter session set nls_date_format = 'yyyy-mm-dd';
with t as (select to_date('02/11/20','mm/dd/rr') src_dte, 1 tgt_mon from dual union all
           select to_date('2020-02-11'),                  2         from dual union all
           select to_date('11-Feb-2020','dd-mon-yyyy'),   3         from dual
         )
select t.src_dte, tgt_mon
     , case when extract(month from t.src_dte) >= t.tgt_mon 
            then add_months(trunc(t.src_dte, 'year'), t.tgt_mon-1)
            else add_months(trunc(t.src_dte, 'year'), t.tgt_mon-1-12)
       end as effective_date
 from t;

Как это работает. Все функции даты возвращают действительную дату. 1. trun c (src_date), 'year') возвращает дату 01-Jan- year 2. Из вышеперечисленного добираться до нужного месяца просто добавляя необходимое количество месяцев (0-11). Так как целью является tgt_mon вычитание 1, а затем добавление к результату trun c дает 1-tgt_mon- год . 3. За предыдущий год возьмите тот же результат сверху и вычтите 1 год (12 месяцев). Нет функции вычитать месяцы, поэтому просто добавьте -12. Это дает 1-tgt_mon-year-1 .

Я считаю, что это лучший метод обработки дат, чем манипулирование строками, но это только мое мнение. Бери если за то что будешь.

0 голосов
/ 11 февраля 2020

Проблема в том, что Oracle применяет операторы конкатенации , прежде чем применяет арифметику c. Поэтому ветвь ELSE вашего оператора CASE:

to_date(t.month || '/' || '01' || '/' || extract(year from t.date)-1, 'mm/dd/yyyy')

будет выполнять что-то вроде '02/01/2019' - 1. Попытка вычесть одно из строки (критически важно, на данный момент это строка, а не дата), не безосновательно приводит к ORA-01722.

Что вам нужно сделать, это обернуть год извлечения во что-то, чтобы заставить минус операция до объединения. Это сделает это:

to_date(t.month || '/' || '01' || '/' || to_char(extract(year from t.date)-1), 'mm/dd/yyyy')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...