简体   繁体   English

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM