2014-04-16 36 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