系統日期設定不正確導致的ORA-01839錯誤

Jet_Zhang發表於2015-05-12

早上收到開發人員發來的郵件,說在一個測試環境中SQL執行報錯,但相同的SQL在另一個測試環境中卻執行經常,叫我幫忙分析一下原因。報錯的SQL為:

SQL> select to_date(substr(cvalidate, 6, 10), 'MM-DD') from lcpol where polno='210010000123931';

select to_date(substr(cvalidate, 6, 10), 'MM-DD') from  lcpol where polno='210010000123931';

*

ERROR at line 1:

ORA-01839: date not valid for month specified

 一看錯誤資訊是ORA-01839: date not valid for month specified。首先想到可能是資料有問題導致在使用TO_DATE報錯。不管怎樣先去求證下是不是真的存在該錯誤。首先連線上說執行報錯的庫,執行SQL,果然如開發人員所說報錯。接著連線上說執行正常的庫,執行SQL,果然Oracle很友好的返回了結果。既然錯誤事實存在,那就要去找出導致錯誤的原因了。

 按照對錯誤的第一反應,先去比對兩邊的資料是否一樣。比對結果有點令人失望,兩邊的資料完全一模一樣。難道是SQL本身存在問題?仔細分析下SQL,應該沒錯啊,雖然使用'MM-DD'格式化的寫法不怎麼好,但也應該不至於導致執行錯誤啊,況且在另外的庫上是執行正確的。那問題到底處在哪呢?難道是兩庫的日期引數設定不一樣?檢視了一下,兩個資料庫的NLS_CHARACTERSET

NLS_NCHAR_CHARACTERSET NLS_DATE_LANGUAGE NLS_DATE_FORMAT設定也是一樣的。好吧,看來問題應該不在資料上。

 再回頭來看一下,在條件polno='210010000123931'下的cvalidate是個什麼值呢?

SQL> select cvalidate from lcpol where polno='210010000123931';  CVALIDATE ---------- 2012-02-29

看來該值確實也比較特殊,4年才會出現一次。但是特殊歸特殊,也不應該報錯了。想到如果直接用該值會怎樣?嗯,那就試試看:

SQL>select to_date(substr('2012-02-29', 6, 10), 'MM-DD') from dual;

ERROR

-----------------------

ERROR at line 1:

ORA-01839: date not valid for month specified

SQL> select to_date(substr('2012-02-29', 6, 10), 'MM-DD') from dual;

TO_DATE(SU

----------

2012-02-29

測試結果還是一樣。正一籌莫展之際,突然注意到雖然使用'MM-DD'來格式化日期,但是結果中仍然還有年的資訊!想到當前的NLS_DATE_FORMAT'YYYY-MM-DD',猜測Oracle會使用當前系統的日期來附加年的資訊。難道是那臺執行錯誤的庫的系統日期不正確,馬上檢視一下,果然,系統日期是2013年!

$ date

Fri Mar  1 18:45:13 CST 2013

馬上聯絡系統管理小組幫忙修正系統日期。在系統日期修改正確後,SQL執行正常,至此問題解決。

 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/13885898/viewspace-1651579/,如需轉載,請註明出處,否則將追究法律責任。

相關文章