[英]Do the TO_DATE function in Oracle 11g PL/SQL have upper/lower limits
我是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日时,会收到以下错误消息…… “在需要数字的地方找到了非数字字符” ……。 当我从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日...这是正确的还是我在这里做错了?
谢谢!
让我们在这里研究数据类型。
sysdate
返回一个date
。 在date
添加number
将返回未来几天的date
。 因此,例如sysdate + 7000
是2033年6月15日。trunc trunc(sysdate + 7000)
也返回一个日期,它只是将时间设置为午夜。 到现在为止还挺好。
当您采用该date
并将其传递给to_date
函数时,就会出现问题。 从逻辑上讲,这没有任何意义。 您已经有一个date
,无需将其转换为date
。 实际上, to_date
不接受date
作为参数。 它只接受一个字符串。 现在,Oracle可以使用会话的nls_date_format
设置将您拥有的date
隐式转换为字符串,这就是它的作用。 最好的情况是,您使用一个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
。 您只应在字符串上调用to_date
。 如果要将date
转换为特定格式的字符串以显示,请使用to_char
而不是to_date
。
回到最初的问题,是的,在Oracle中构成有效日期存在限制。 有效date
必须在公元前4712年1月1日(6700年以前)到9999年12月31日(从现在起7900年)之间。 看来您没有超出这些限制的任何地方。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.