2016-02-29 50 views
5

今天我們都知道這是一個特殊的日子。它的0123p閏年Oracle DB Ora-01839:日期在指定的月份內無效。 29-02-2016閏年

我們收到一條錯誤消息從我們的Oracle數據庫的一些表。錯誤是:Oracle ORA-01839: date not valid for month specified

例如一個簡單的選擇,其中發生錯誤:select * from table where table_date > sysdate -0.1;

對於其他表這個選擇是沒有問題的,只是某些表。

有沒有辦法解決這個問題?因爲我們今天無法使用很多表格。

我們正在使用Oracle 12c

+1

列'table_date'的數據類型是什麼? –

+0

@WernfriedDomscheit它的一個'date' – Patrick

+1

'是否從選擇table_date ...'也得到這個錯誤 - 也許是被隱式轉換失敗不同的列?它是一張桌子還是一張視圖(用來計算某種東西);還是它有一個虛擬列?會話中出現錯誤的NLS_DATE_FORMAT是什麼?你是否在特定的客戶端看到了這一點,並且可以在SQL \ * Plus中重現? –

回答

7

經過深入細緻的研究,它清楚爲什麼我們的一些選擇的今天不上班。該錯誤是由關鍵字interval及其已知問題引起的。 (或者它的ANSI/ISO spec怎麼說,它應該工作,第206頁的第205頁/頂的底部)

下面是從oracle community blog一個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 

回答

這就是INTERVALs的工作原理。閏年是 問題中最少的; 3月31日增加1個月導致同樣的錯誤。如果您要 要確保結果是有效日期,請使用 ADD_MONTHS。 (有添加多年沒有獨立的功能;使用 ADD_MONTH(SYSDATE,12 * N)來獲得日期是N年從現在開始。)


爲什麼它會發生在我們的例子:

在我們的例子中,我們使用虛擬專用數據庫,我們的一些因爲安全原因表。並且我們在大多數選擇中應用了interval關鍵字。

該怎麼做:

使用ADD_MONTHS代替。

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

只是一個說明,對於夏令時,行爲也是不同的。比較'TIMESTAMP'2015-10-25 01:30:00歐洲/柏林'+ INTERVAL'1'MONTH'與'ADD_MONTHS(TIMESTAMP'2015-10-25 01:30:00歐洲/柏林',1)' –

+0

我們錯誤地得到類似於下面的代碼(由於ODP.NET使用INTERVAL與'DbFunctions.AddYears',導致此Oracle異常今天導致): 'DataSet.Where(e => e.Date> = DbFunctions.AddYears(DateTime .Now,-1))' – Trent

+0

謝謝你。我想知道即使支持日期+時間間隔,如果您不打算支持跨越月份邊界和閏年,這是甚麼意義... –

相關問題