2014-02-05 3 views
1

В Oracle, как мне вычесть месяц из временной метки, сохраняющей миллисекунду.В Oracle, как мне вычесть месяц из временной метки, сохраняющей миллисекундную часть

Я использую функцию add_months, но она обрезает миллисекунды. Есть ли встроенная функция, или мне нужно вручную извлечь месячную часть метки времени и добавить к ней?

+1

@Klas: К сожалению, этот вопрос не появлялся в моем поиске результат. – Parvez

+1

Причина: 'add_months' ожидает параметр' DATE', а не тип данных TIMESTAMP. –

+0

@ Wernfried: Да, но add_months работает с типом данных TIMESTAMP, и я не понял этого, пока не увидел проблему в моем результате. – Parvez

ответ

3

Вы можете сделать это, используя год в месяц интервал буквального:

clear screen; 

select current_timestamp      as res_1 
    , current_timestamp - interval '1' month as res_2 
    from dual 

Результат:

RES_1       RES_2         
------------------------------ ----------------------------- 
05-FEB-14 02.02.32.383089000 05-JAN-14 02.02.32.383089000 

При использовании add_months() функции, преобразование типов данных происходит - значение timestamp данных type становится значением типа данных date, который не имеет дробных секунд.

Как @jonearles абсолютно правильно указано в комментарии к ответу, используя представленный выше метод для вычитания одного или нескольких месяцев из заданного значения, сохраняющего миллисекунды, может привести к ORA-01839: date not valid for month specified.

Чтобы предотвратить эту ошибку от выскакивают, запрос можно переписать следующим образом:

clear screen; 

with t1(col) aS(
    select current_timestamp      from dual union all 
    select timestamp '2000-03-30 12:12:12.123' from dual union all 
    select timestamp '2014-03-30 01:12:59.64567' from dual 
) 
select col as cur          
    , cast(add_months(col, -1) as timestamp) + (col - cast(col as date)) as prev 
    from t1 

Результат:

CUR         PREV       
-------------------------------------- ------------------------------- 
14-FEB-14 01.45.46.344187000 PM  14-JAN-14 01.45.46.344187000 PM 
30-MAR-00 12.12.12.123000000 PM  29-FEB-00 12.12.12.123000000 PM 
30-MAR-14 01.12.59.645670000 AM  28-FEB-14 01.12.59.645670000 AM 
+0

SELECT current_timestamp + INTERVAL '-1' MONTH from dual; также работает. – Parvez

+0

Интервальные литералы обычно очень полезны, но, к сожалению, версия месяца имеет некоторые большие проблемы. Он просто меняет номер месяца, что может привести к недопустимым датам. Например: 'select date '2000-03-30' - интервал '1' month from dual;'. –

Смежные вопросы