2016-02-29 43 views
5

Wszyscy wiemy, że dziś jest szczególny dzień. Jest to 29th of February 2016 z rok przestępny.Oracle DB Ora-01839: data nie jest poprawna dla określonego miesiąca. 29-02-2016 rok przestępny

Otrzymujemy komunikat o błędzie z niektórych tabel w naszej bazie danych Oracle. Błąd jest następujący: Oracle ORA-01839: date not valid for month specified.

Na przykład prosta wybrać gdzie pojawia się błąd: select * from table where table_date > sysdate -0.1;

Dla innych tabel to wybierz sprawia żadnego problemu, tylko na niektórych stołach.

Czy istnieje sposób rozwiązania tego problemu? Ponieważ nie jesteśmy dzisiaj w stanie korzystać z wielu tabel.

Używamy Oracle 12c.

+1

Jaki jest typ danych kolumny 'table_date'? –

+0

@ WernfriedDomscheit jego 'date' – Patrick

+1

Czy' select table_date from ... 'również pobiera ten błąd - może jest to inna kolumna, która kończy się niepowodzeniem przy niejawnej konwersji? Czy jest to tabela lub widok (który coś wylicza); czy ma wirtualną kolumnę? Co to jest NLS_DATE_FORMAT w sesji, która otrzymuje błąd? Czy widzisz to w konkretnym kliencie i czy możesz powielić w SQL \ * Plus? –

Odpowiedz

7

Po intensywnych badaniach jasne jest, dlaczego niektóre z naszych wyborów nie działają dzisiaj. Błąd jest spowodowany słowem kluczowym interval i jego znanym problemem. (Lub jest to, w jaki sposób ANSI/ISO spec mówi to powinno działać, dolna strona 205/górnej stronie 206)

Oto qoute z oracle community blog:

Pytanie:

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 

odpowiedzi:

Tak właśnie działają INTERWAŁY. Lata przestępne są najmniejsze z problemów związanych z ; dodanie 1 miesiąca do 31 marca powoduje ten sam błąd. Jeśli chcesz, aby wynik był prawidłowy DATE, użyj ADD_MONTHS. (Nie ma oddzielny funkcja dodawania lat; używać ADD_MONTH (sysdate, 12 * N), aby uzyskać informacje o dacie, która jest n lat od teraz.)


Dlaczego to się dzieje w naszym przypadku:

W naszym przypadku użyliśmy wirtualnej prywatnej bazy danych dla niektórych naszych stołów ze względów bezpieczeństwa. I tam zastosowaliśmy słowo kluczowe interval w większości wyborów.

Co zrobić zamiast:

Zastosowanie ADD_MONTHS zamiast.

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

Tylko uwaga, dla czasu letniego zachowanie również się różni. Porównaj "TIMESTAMP" 2015-10-25 01:30:00 Europa/Berlin "+ INTERWAŁ" 1 "MIESIĄC" vs. "ADD_MONTHS (TIMESTAMP" 2015-10-25 01:30:00 Europa/Berlin ", 1)' –

+0

My omyłkowo mamy kod podobny do następującego (który spowodował ten wyjątek Oracle dzisiaj ze względu na ODP.NET używający INTERVAL z 'DbFunctions.AddYears'): ' DataSet.Where (e => e.Date> = DbFunctions.AddYears (DateTime . Teraz, -1)) ' – Trent

+0

Dziękuję za to. Zastanawiam się, jaki jest sens nawet wspierania daty + interwału, jeśli nie zamierzasz obsługiwać przekraczania granic miesiąca i lat przestępnych ... –