2009-12-31 73 views
4

本质上,我有一个查询负责在上个月内获取所有记录(使用特定的过滤器)。我正在使用Oracle的interval关键字,并且所有工作都很好,直到今天(2009年12月31日)。我正在使用的代码是一个月的时间间隔不能在31日工作?

select (sysdate - interval '1' month) from dual 

和错误,我得到它

ORA-01839: date not valid for month specified 

我如何使用间隔关键字可与任何兼容的日期?或者如果任何人有更好的方法来解决这个问题,我全都耳熟能详。

谢谢。

回答

9

尝试

select add_months(sysdate,-1) from dual 
+0

谢谢。 :) 任何想法,为什么add_months()的作品,但不是间隔?是因为12月份有31天,11月只有30天? – Mike 2009-12-31 13:31:01

+0

不完全确定,但INTERVAL是另一种数据类型(类似于DATE和TIMESTAMP),Steve Feuerstein的PL/SQL书中有关它的所有内容看起来相当复杂。我通常会去做最简单的事情!自Oracle 7开始,ADD_MONTHS一直在使用DATE类型(即SYSDATE)。 如果要在午夜边界开始,可能需要使用ADD_MONTHS(trunc(sysdate), - 1)。 – CMG 2009-12-31 13:36:54

+0

完美!感谢您的澄清和代码修改。 :) – Mike 2009-12-31 13:38:48

2

不是学究气十足......

的要求是不是很完美规定明确。 “上个月内”的业务意味着什么?大多数人会认为这意味着在这种情况下我会使用“当前日历月内”:

TRUNC(SYSDATE,'MM') 

否则,也许他们希望1个月的当前日期之前的任意时间段 - 但后来怎么办你定义了那个?正如您发现的,INTERVAL '1' MONTH只是从日期的月份部分中减去一个 - 例如15-JAN-2009 - INTERVAL '1' MONTH返回15-DEC-1999。对于某些日期,这会导致日期无效,因为不是所有的月份都有相同的天数。

ADD_MONTHS通过返回本月的最后一天来解决此问题,例如, ADD_MONTHS(31-DEC-2009,-1)返回2009年11月30日。

另一种可能性是企业实际上想要使用平均月份 - 例如, 365/12约为30.4。他们可能希望你使用​​,尽管当然这样的12次迭代只能涵盖一年中的360天。