2014-04-16 50 views
0

我是Oracle開發新手,仍然發現它的許多功能以及PL/SQL和SQL Server的T-SQL之間的差異。Oracle 11g PL/SQL中的TO_DATE函數是有上限還是下限的

所以我的'項目'是創建一個函數,可以從未來或過去生成一個隨機的日期。用戶應該能夠指定應該創建日期的上限/下限。

我可能爲時已晚,但爲了保持公正性,我將跳過爲什麼函數做什麼以及如何做的細節。對於實際問題重要和有意義的是以下行爲。

BEGIN 
    SYS.DBMS_OUTPUT.PUT_LINE(TO_DATE(TRUNC(SYSDATE + 6469), 'yyyy/mm/dd')); -- Dec 31, 2031 
    SYS.DBMS_OUTPUT.PUT_LINE(TO_DATE(TRUNC(SYSDATE - 4853), 'yyyy/mm/dd')); -- Jan 01, 2001 
    SYS.DBMS_OUTPUT.PUT_LINE(TO_DATE(TRUNC(SYSDATE + 7000), 'yyyy/mm/dd')); -- ERROR 
END 

簡單地說,當我足夠的天添加到系統日期超過2031年12月31日我收到以下錯誤消息... 「非數字字符被發現,其中一個數字,預計」 ......。我遇到同樣的問題,當我足夠減去從天將系統日期前的日期Jan 01 2001

當我刪除它不會破壞格式,但返回一個不可能日期...

BEGIN 
    -- returns 15-JUN-33 
    -- June 33rd 2015!! 
    SYS.DBMS_OUTPUT.PUT_LINE(TO_DATE(TRUNC(SYSDATE + 7000))); 
END 

因此,在我看來,這種函數有一些日期範圍限制... 2001年1月01日 - 2031年12月31日......這是真的還是我在這裏做錯了什麼?

謝謝!

+0

暫時忘掉所有這些功能。你犯的錯誤可能會影響你的結果。相反,試試這個:to_char(sysdate + 7000,'yyyy/mm/dd')。至於你做錯了什麼,請閱讀to_date和trunc的文檔。注意他們返回的數據類型。 –

回答

4

讓我們通過這裏的數據類型。

sysdate返回date。將number添加到date會在將來多天返回date。因此,例如,sysdate + 7000是2033年6月15日。trunc(sysdate + 7000)也返回一個日期,它只是將時間設置爲午夜。到現在爲止還挺好。

問題出現在您將date傳遞給to_date函數時。從邏輯上講,這沒有意義。您已有date,因此無需將其轉換爲date。實際上,to_date不接受date作爲參數。它只接受一個字符串。現在,Oracle可以使用會話的nls_date_format設置隱式地將date轉換爲字符串,這就是它在這裏所做的。最好的情況下,你正在採取date,將其隱式轉換爲字符串,然後將該字符串顯式轉換回與您開始使用的date完全相同的字符串。但是,如果您的會話nls_date_format發生與您向to_date提供的格式掩碼不匹配的情況,那麼您可能會收到錯誤,這是您在此處看到的錯誤。

通過一個示例,讓我們使用2033年6月15日午夜的日期。如果您打電話to_date,Oracle必須使用會話的nls_date_format將日期轉換爲字符串。如果你在美國,並且你沒有改變任何關於你的客戶,你的nls_date_format可能是DD-MON-RR。這意味着當您的日期被傳遞到to_date時,您的日期將被轉換爲字符串15-JUN-33。因此,從邏輯上講,你想如果你看它這樣做類似的東西

dbms_output.put_line(to_date('15-JUN-33', 'yyyy/mm/dd')); 

,很明顯,該格式掩碼不匹配導致一個錯誤的字符串格式。如果您的nls_date_format更接近to_date中的格式掩碼,那麼to_date調用可能會成功運行,但返回的日期與您預期的不同(例如,切換月份和日期)。

簡單的答案是,你永遠不應該在一天中撥打to_date。您只能在字符串上撥打to_date。如果要將date轉換爲特定格式的字符串進行顯示,請使用to_char而不是to_date

回到原始問題,是的,在Oracle中構成有效日期的限制是有限制的。有效的date必須在公元前4712年1月1日(6700年前)至9999年12月31日(現在7900年)之間有效。看起來你並沒有超出這些限制。

+0

非常感謝你的解釋。我正在模擬一個我在其他地方看到的例子,並錯誤地認爲他們所做的一定是正確的。 –

+0

很好的解釋@Justin洞穴 – Siva