[英]Do the TO_DATE function in Oracle 11g PL/SQL have upper/lower limits
I am new to Oracle development and am still discovering a lot of it's capabilities and the differences between PL/SQL and SQL Server's T-SQL. 我是Oracle开发的新手,仍然发现它的许多功能以及PL / SQL和SQL Server的T-SQL之间的差异。
So my 'project' is to create a function that would generate a random date from either the future or the past. 因此,我的“项目”是创建一个函数,该函数将从未来或过去生成随机日期。 The user should be able to specify the upper/lower bounds in which the date should be created.
用户应该能够指定创建日期的上限/下限。
I may be too late but in the interest of breivity I will skip the details of why the function does what it does and how. 我可能为时已晚,但是出于简洁的考虑,我将跳过有关该函数为何执行其功能以及如何执行此操作的详细信息。 What is important and pertinent to the actual questions is the following behavoir.
以下是与实际问题相关的重要和重要的行为。
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
Simply put, when I add enough days to the SYSTEM date to exceed Dec 31, 2031 I get the following error message ... "a non-numeric character was found where a numeric was expected" ... . 简而言之,当我在SYSTEM日期中添加足够的天数以超过2031年12月31日时,会收到以下错误消息…… “在需要数字的地方找到了非数字字符” ……。 I experience the same problem when I subtract enough days from the SYSTEM date to pre-date Jan 01, 2001.
当我从SYSTEM日期减去2001年1月1日之前的日期时,我遇到了同样的问题。
When I remove the format it's doesn't break but returns an impossible date ... 当我删除格式时,它不会中断但会返回一个不可能的日期...
BEGIN
-- returns 15-JUN-33
-- June 33rd 2015!!
SYS.DBMS_OUTPUT.PUT_LINE(TO_DATE(TRUNC(SYSDATE + 7000)));
END
So it appears to me that there is some sort of date range limit on this function ... JAN 01, 2001 - DEC 31, 2031 ... Is that true or am I doing something wrong here? 因此,在我看来,此功能有某种日期范围限制... 2001年1月1日-2031年12月31日...这是正确的还是我在这里做错了?
Thanks! 谢谢!
Let's work through the data types here. 让我们在这里研究数据类型。
sysdate
returns a date
. sysdate
返回一个date
。 Adding a number
to a date
returns a date
that many days in the future. 在
date
添加number
将返回未来几天的date
。 So, for example, sysdate + 7000
is June 15, 2033. trunc(sysdate + 7000)
also returns a date, it just sets the time to midnight. 因此,例如
sysdate + 7000
是2033年6月15日。trunc trunc(sysdate + 7000)
也返回一个日期,它只是将时间设置为午夜。 So far, so good. 到现在为止还挺好。
The problem comes when you take that date
and pass it to the to_date
function. 当您采用该
date
并将其传递给to_date
函数时,就会出现问题。 Logically, that doesn't make sense. 从逻辑上讲,这没有任何意义。 You already have a
date
, there is no need to convert it to a date
. 您已经有一个
date
,无需将其转换为date
。 Practically, to_date
does not accept a date
as a parameter. 实际上,
to_date
不接受date
作为参数。 It only accepts a string. 它只接受一个字符串。 Now, Oracle can implicitly convert the
date
you have to a string using your session's nls_date_format
setting which is what it does here. 现在,Oracle可以使用会话的
nls_date_format
设置将您拥有的date
隐式转换为字符串,这就是它的作用。 Best case, you're taking a date
, implicitly converting that to a string, then explicitly converting that string back to exactly the same date
that you started with. 最好的情况是,您使用一个
date
,将其隐式转换为字符串,然后将该字符串显式转换回与起始date
完全相同的date
。 If your session's nls_date_format
happens not to match the format mask that you're providing to the to_date
, however, you'll likely get an error which is what you're seeing here. 但是,如果会话的
nls_date_format
恰好与您提供给to_date
的格式掩码不匹配,那么您很可能会收到一个错误,这就是您在此处看到的。
Walking through an example, let's use the date of midnight on June 15, 2033. If you call to_date
on that, Oracle has to convert the date to a string using your session's nls_date_format
. 我们来看一个例子,让我们使用2033年6月15日午夜的日期。如果您在该日期调用
to_date
,Oracle必须使用会话的nls_date_format
将日期转换为字符串。 If you're in the United States and you haven't changed anything about your client, your nls_date_format
is probably DD-MON-RR
. 如果您在美国并且尚未更改任何有关客户的信息,则您的
nls_date_format
可能是DD-MON-RR
。 That means that your date gets converted to the string 15-JUN-33
when it is passed in to to_date
. 这意味着您的日期在传递给
to_date
时将转换为字符串15-JUN-33
。 So, logically, you're trying to do something like 因此,从逻辑上讲,您正在尝试做类似的事情
dbms_output.put_line( to_date( '15-JUN-33', 'yyyy/mm/dd' ));
When you look at it this way, it's obvious that the format mask doesn't match the format of the string which causes an error. 当您以这种方式查看时,很明显格式掩码与导致错误的字符串格式不匹配。 If your
nls_date_format
is closer to the format mask in your to_date
, it is possible that the to_date
call will run successfully but return a different date than you expect (switching the month and the day for example). 如果您的
nls_date_format
更接近to_date
的格式掩码,则to_date
调用可能会成功运行,但返回的日期与您期望的日期不同(例如,切换月份和日期)。
The simple answer is that you should never call to_date
on a day. 简单的答案是,您绝对
to_date
在一天中致电to_date
。 You should only call to_date
on a string. 您只应在字符串上调用
to_date
。 If you want to convert a date
into a string in a particular format for display, use to_char
not to_date
. 如果要将
date
转换为特定格式的字符串以显示,请使用to_char
而不是to_date
。
Going back to the original question, yes there are limits to what constitutes a valid date in Oracle. 回到最初的问题,是的,在Oracle中构成有效日期存在限制。 A valid
date
must be between Jan 1, 4712 BC (6700 years ago) to Dec 31, 9999 (7900 years from now). 有效
date
必须在公元前4712年1月1日(6700年以前)到9999年12月31日(从现在起7900年)之间。 It doesn't appear that you are anywhere near exceeding those limits. 看来您没有超出这些限制的任何地方。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.