2016-02-29 15 views
5

Sappiamo tutti che oggi è un giorno speciale. È il 29th of February 2016 di un anno bisestile .Oracle DB Ora-01839: data non valida per il mese specificato. 29-02-2016 anno bisestile

Riceviamo un messaggio di errore da alcune tabelle nel nostro DB Oracle. L'errore è: Oracle ORA-01839: date not valid for month specified.

Per esempio un semplice selezionare in cui si verifica l'errore: select * from table where table_date > sysdate -0.1;

Per gli altri tavoli questo selezionare fa nessun problema, solo per alcune delle tabelle.

C'è un modo per risolvere questo problema? Perché oggi non siamo in grado di utilizzare molti tavoli.

Stiamo usando Oracle 12c.

+1

Qual è il tipo di dati della colonna 'table_date'? –

+0

@WernfriedDomscheit è un 'date' – Patrick

+1

Anche 'seleziona table_date da ...' ottiene questo errore - forse è una colonna diversa che non funziona nella conversione implicita? È una tabella o una vista (che calcola qualcosa); o ha una colonna virtuale? Che cos'è il NLS_DATE_FORMAT nella sessione in cui viene visualizzato l'errore? Stai vedendo questo in un particolare client, e puoi riprodurlo in SQL \ * Plus? –

risposta

7

Dopo un'intensa ricerca, è chiaro perché alcuni dei nostri selezionati non funzionano oggi. L'errore è causato dalla parola chiave interval ed è un problema noto. (O è come il ANSI/ISO spec dice dovrebbe funzionare, in fondo alla pagina 205/inizio pagina 206)

Ecco un 'offerta dal oracle community blog:

Domanda:

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 

risposta:

Ecco come funzionano INTERVAL. Gli anni bisestili sono il minimo del problema ; aggiungendo 1 mese al 31 marzo risulta lo stesso errore. Se si si desidera assicurarsi che il risultato sia una DATA valida, quindi utilizzare ADD_MONTHS. (Non c'è funzione separata per l'aggiunta di anni; utilizzare ADD_MONTH (SYSDATE, 12 * n) per ottenere la data che è N anni da oggi.)


Perché succede nel nostro caso:

Nel nostro caso, abbiamo utilizzato un database privato virtuale per alcune delle nostre tabelle per motivi di sicurezza. E lì abbiamo applicato la parola chiave interval nella maggior parte dei casi selezionati.

Cosa fare invece:

Usa ADD_MONTHS invece.

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

Solo una nota, per l'ora legale, anche il comportamento è diverso. Confronta 'TIMESTAMP '2015-10-25 01:30:00 Europa/Berlino' + INTERVALLO '1' MESE' contro' ADD_MONTHS (TIMESTAMP '2015-10-25 01:30:00 Europa/Berlino', 1) ' –

+0

Abbiamo erroneamente codice simile al seguente (che ha causato questa eccezione Oracle oggi a causa di ODP.NET utilizzando INTERVAL con 'DbFunctions.AddYears'): ' DataSet.Where (e => e.Date> = DbFunctions.AddYears (DateTime .Now, -1)) ' – Trent

+0

Grazie per questo. Mi chiedo quale sia il motivo di sostenere anche la data + intervallo se non si intende supportare il superamento dei confini del mese e degli anni bisestili ... –

Problemi correlati