Oracle DB Ora-01839:日期对指定的月份无效.闰年29-02-2016

Pat*_*ick 5 oracle leap-year oracle12c

我们都知道今天是特殊的一天.它29th of February 2016闰年.

我们收到Oracle DB中某些表的错误消息.错误是:Oracle ORA-01839: date not valid for month specified.

例如,发生错误的简单选择:select * from table where table_date > sysdate -0.1;

对于其他表,这个选择没有问题,只是对于某些表.

有没有办法解决这个问题?因为我们今天无法使用很多桌子.

我们正在使用Oracle 12c.

Pat*_*ick 8

经过深入研究,明确了为什么我们的一些选择今天不起作用.该错误是由关键字interval及其已知问题引起的.(或者它是ANSI/ISO规范说它应该工作的方式,第205页底部/第206页上方)

这是来自oracle社区博客的qoute :

问题:

select to_date('2012-feb-29','yyyy-mon-dd') + interval '1' year as dt from dual;

ORA-01839: date not valid for month specified
01839. 00000 -  "date not valid for month specified"
*Cause:    
*Action:

select to_date('2012-feb-29','yyyy-mon-dd') + interval '2' year as dt from dual;

ORA-01839: date not valid for month specified
01839. 00000 -  "date not valid for month specified"
*Cause:    
*Action:

select to_date('2012-feb-29','yyyy-mon-dd') + interval '3' year as dt from dual;

ORA-01839: date not valid for month specified
01839. 00000 -  "date not valid for month specified"
*Cause:    
*Action:

select to_date('2012-feb-29','yyyy-mon-dd') + interval '4' year as dt from dual;

29-FEB-16 00:00:00


select to_date('2012-feb-29','yyyy-mon-dd') + interval '1' day as dt from dual;

01-MAR-12 00:00:00

select to_date('2012-feb-29','yyyy-mon-dd') + interval '1' month as dt from dual;

29-MAR-12 00:00:00
Run Code Online (Sandbox Code Playgroud)

答案:

这就是INTERVAL的工作方式.闰年是问题的最小年份; 将1个月添加到3月31日会导致相同的错误.如果要确保结果是有效的DATE,请使用ADD_MONTHS.(添加年份没有单独的功能;使用ADD_MONTH(SYSDATE,12*n)来获取从现在起n年的DATE.)


为什么会发生在我们的案例中:

在我们的例子中,出于安全原因,我们在某些表中使用了虚拟专用数据库.我们interval在大多数选择中应用了关键字.

该怎么做:

ADD_MONTHS改用.

select add_months(to_date('2012-feb-29','yyyy-mon-dd'), 12) as dt from dual;
Run Code Online (Sandbox Code Playgroud)

  • 只是注意,对于夏令时 - 行为也是不同的.比较`TIMESTAMP'2015-10-25 01:30:00欧洲/柏林'+ INTERVAL'1'MONTH`与`ADD_MONTHS(TIMESTAMP'2015-10-25 01:30:00欧洲/柏林',1) (3认同)