我是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日......这是真的还是我在这里做错了什么?
谢谢!
答案 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年)之间。您似乎没有超出这些限制。