views:

67

answers:

2

Essentially, I have a query that is responsible for fetching all records (with specific filters) within the last month. I'm using Oracle's interval keyword and all was working great until today (December 31st, 2009). The code I'm using is

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

and the error I get it

ORA-01839: date not valid for month specified

How can I use the interval keyword to be compatible with any date? Or if anyone has a better way of approaching the issue, I'm all ears.

Thank you.

+5  A: 

try

select add_months(sysdate,-1) from dual
CMG
Thank you. :)Any ideas as to why add_months() works but not interval? Is it because since December has 31 days and November only has 30?
Mike
Not exactly sure, but INTERVAL is another data type (similar to DATE and TIMESTAMP) and all the stuff in Steve Feuerstein's PL/SQL book about it looks quite complicated. I usually go for the simplest thing that works! ADD_MONTHS has been around since Oracle 7 and works on DATE types (which SYSDATE is).You might want to use ADD_MONTHS(trunc(sysdate),-1) if you want to start at the midnight boundary.
CMG
Perfect! Thanks for the clarification and code modification. :)
Mike
There are a lot of useful built-in functions like ADD_MONTHS which might be useful for the sort of thing you're doing. Eg select last_day(add_months(trunc(sysdate),-1))+1 from dualwill give you the first day of the current month(by going to the last day of the previous month and adding 1)This might be more useful if you want to get records just from the current month.
CMG
+1  A: 

Being pedantic...

The requirements are not quite specified perfectly unambiguously. What does the business mean by "within the last month"? Most people would take that to mean "within the current calendar month" in which case I'd use:

TRUNC(SYSDATE,'MM')

Otherwise, perhaps they want an arbitrary period of 1 month prior to the current date - but then how do you define that? As you've found, INTERVAL '1' MONTH simply subtracts one from the month portion of the date - e.g. 15-JAN-2009 - INTERVAL '1' MONTH returns 15-DEC-1999. For some dates, this results in an invalid date because not all months have the same number of days.

ADD_MONTHS resolves this by returning the last day in the month, e.g. ADD_MONTHS(31-DEC-2009,-1) returns 30-NOV-2009.

Another possibility is that the business actually wants to use an average month period - e.g. 365/12 which is approximately 30.4. They might want you to use SYSDATE-30, although of course twelve iterations of this will only cover 360 days of the year.

Jeffrey Kemp