【问题标题】:Do the TO_DATE function in Oracle 11g PL/SQL have upper/lower limitsOracle 11g PL/SQL 中的 TO_DATE 函数是否有上限/下限
【发布时间】:2014-04-16 22:09:45
【问题描述】:

我是 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 日......这是真的还是我在这里做错了什么?

谢谢!

【问题讨论】:

  • 暂时忘记所有这些功能。你犯的错误可能会扭曲你的结果。相反,试试这个:to_char(sysdate + 7000, 'yyyy/mm/dd')。至于你做错了什么,请阅读 to_date 和 trunc 上的文档。注意它们返回的数据类型。

标签: sql oracle date oracle11g


【解决方案1】:

让我们来看看这里的数据类型。

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

当您将 date 传递给 to_date 函数时,问题就来了。从逻辑上讲,这没有任何意义。您已经拥有date,无需将其转换为date。实际上,to_date 不接受 date 作为参数。它只接受一个字符串。现在,Oracle 可以使用会话的nls_date_format 设置将您必须的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。如果要将date 转换为特定格式的字符串进行显示,请使用to_char 而不是to_date

回到最初的问题,是的,Oracle 中的有效日期是有限制的。有效的date 必须在公元前 4712 年 1 月 1 日(6700 年前)到 9999 年 12 月 31 日(从现在起 7900 年)之间。您似乎没有超过这些限制。

【讨论】:

  • 非常感谢您的解释。我正在模拟我在其他地方看到的一个示例,并错误地假设他们所做的事情一定是正确的。
  • 很好的解释@Justin Cave
猜你喜欢
  • 1970-01-01
  • 2017-07-04
  • 1970-01-01
  • 2014-10-10
  • 1970-01-01
  • 1970-01-01
  • 2015-07-01
  • 2014-02-01
  • 1970-01-01
相关资源
最近更新 更多