Oracle 11g PL / SQL中的TO_DATE函数是否具有上限/下限

时间:2014-04-16 22:09:46

标签: sql oracle date oracle11g

我是Oracle开发的新手,我仍然发现它的很多功能以及PL / SQL和SQL Server的T-SQL之间的差异。

所以我的项目'是创建一个从未来或过去生成随机日期的函数。用户应该能够指定应在其中创建日期的上限/下限。

我可能为时已晚,但为了突发事件的利益,我将跳过为什么功能会做它的功能和方式的细节。实际问题的重要和相关之处是以下行为。

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

简单地说,当我添加足够的日期到SYSTEM日期超过2031年12月31日时,我收到以下错误消息... "找到了一个非数字字符,其中数字是预期的&# 34; ......当我从SYSTEM日期到2001年1月1日之前减去足够的天数时,我遇到了同样的问题。

当我删除格式时,它不会中断,但会返回一个不可能的日期......

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

所以在我看来,这个功能有一些日期范围限制... 2001年1月1日 - 2031年12月31日......这是真的还是我在这里做错了什么?

谢谢!

1 个答案:

答案 0 :(得分:4)

让我们在这里处理数据类型。

sysdate返回date。将number添加到date会在将来的许多天内返回date。因此,例如,sysdate + 7000是2033年6月15日。trunc(sysdate + 7000)也会返回一个日期,它只是将时间设置为午夜。到目前为止,非常好。

问题来自于您date并将其传递给to_date函数。从逻辑上讲,这没有意义。您已经拥有date,无需将其转换为date。实际上,to_date不接受date作为参数。它只接受一个字符串。现在,Oracle可以使用会话的date设置隐式地将您拥有的nls_date_format转换为字符串,这就是它在这里所做的。最好的情况是,您正在使用date,将其隐式转换为字符串,然后将该字符串显式转换回与您开始时完全相同的date。如果您的会话的nls_date_format与您提供给to_date的格式掩码不匹配,那么您可能会收到错误,这就是您在此处看到的错误。

通过一个例子,让我们使用2033年6月15日午夜的日期。如果你打电话给to_date,Oracle必须使用会话的nls_date_format将日期转换为字符串。如果您在美国且未对客户进行任何更改,则nls_date_format可能是DD-MON-RR。这意味着您的日期在传递到15-JUN-33时会转换为字符串to_date。所以,从逻辑上讲,你正在尝试做类似

的事情
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年)之间。您似乎没有超出这些限制。