使用 sysdate 时的 Oracle SQL,为啥它没有给出预期的结果

Posted

技术标签:

【中文标题】使用 sysdate 时的 Oracle SQL,为啥它没有给出预期的结果【英文标题】:Oracle SQL while using the sysdate, why it is not giving the expected result使用 sysdate 时的 Oracle SQL,为什么它没有给出预期的结果 【发布时间】:2018-04-15 23:19:29 【问题描述】:
select '1'
  from Dual
 where to_date('11-APR-2018','DD-MM-YYYY') between to_date(sysdate - 14,'DD-MM-YYYY')
                                               and to_date(sysdate,'DD-MM-YYYY')

为什么这个查询没有给出正确的结果,当我用硬编码日期替换 sysdate 时,它​​给出了预期的结果,所以在使用 sysdate 时,为什么它没有给出预期的结果,请你帮我解决一下

【问题讨论】:

这是***.com/questions/23398632/…的副本 SYSDATE 是一个返回 DATE 的函数,因此您正在使用 to_date 将 DATE 转换为 DATE - 您可以删除这些 它给你带来什么结果?它是否返回'1'以外的东西?它会抛出错误吗?也许还有别的?请编辑您的问题(使用标签下方的edit 按钮)并包含此信息。谢谢。 从不,永远不要在已经是日期的值上调用 to_date()。这将首先将date 值转换为varchar,然后将varchar 转换回最初的date 您获取一个字符串'11-APR-2018' 并尝试将其转换为日期。但是'DD-MM-YYYY' 的格式不匹配。你没有收到错误吗?那么即使您使用了'DD-MON-YYYY',您仍然会依赖会话语言设置来匹配APR'。如果设置为法语,这将失败。因此,无论何时执行此操作,请使用第三个参数指定语言:to_date('11-APR-2018','DD-MON-YYYY', nls_date_language=english')。但是,无论如何,我宁愿使用日期文字(即date '2018-04-11')。 【参考方案1】:

TO_DATE( date_string, format_model ) 接受两个字符串作为参数;但是,您将SYSDATE(或SYSDATE - 14)作为第一个参数传递,它不是字符串,因为它已经是DATE 数据类型。 Oracle 试图提供帮助,并将使用 NLS_DATE_FORMAT 会话参数将日期隐式转换为字符串,以便您的查询有效:

SELECT '1'
FROM   DUAL
WHERE  TO_DATE( '11-APR-2018', 'DD-MM-YYYY' )
       BETWEEN TO_DATE(
                 TO_CHAR(
                   SYSDATE - 14,
                   ( SELECT VALUE
                     FROM   NLS_SESSION_PARAMETERS
                     WHERE  PARAMETER = 'NLS_DATE_FORMAT' )
                 ),
                 'DD-MM-YYYY'
               )
       AND     TO_DATE(
                 TO_CHAR(
                   SYSDATE,
                   ( SELECT VALUE
                     FROM   NLS_SESSION_PARAMETERS
                     WHERE  PARAMETER = 'NLS_DATE_FORMAT' )
                 ),
                 'DD-MM-YYYY'
               )

如果您的 NLS_DATE_FORMATDD-MM-YYYY 匹配,那么您的查询将有效:

SQL Fiddle

查询 1

ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MM-YYYY'

SELECT '1'
FROM   DUAL
WHERE  TO_DATE( '11-APR-2018', 'DD-MM-YYYY')
         BETWEEN TO_DATE( SYSDATE - 14, 'DD-MM-YYYY' )
         AND     TO_DATE( SYSDATE,      'DD-MM-YYYY' )

Results

| '1' |
|-----|
|   1 |

但是,如果您的 NLS_DATE_FORMAT 不匹配,那么您几乎肯定会遇到异常,因为当您尝试以 @ 格式读取时,SYSDATE - 14SYSDATE 格式为 MM-DD-YYYY 的月份无效987654338@.

查询 2

ALTER SESSION SET NLS_DATE_FORMAT = 'MM-DD-YYYY'

SELECT '1'
FROM   DUAL
WHERE  TO_DATE( '11-APR-2018', 'DD-MM-YYYY')
         BETWEEN TO_DATE( SYSDATE - 14, 'DD-MM-YYYY' )
         AND     TO_DATE( SYSDATE,      'DD-MM-YYYY' )

Results

ORA-01843: not a valid month

最简单的解决方案不是将日期转换为日期,而是直接使用日期(并在具有固定日期值的地方使用 DATE 文字):

SELECT '1'
FROM   DUAL
WHERE  DATE '2018-04-11' BETWEEN SYSDATE - 14 AND SYSDATE;

【讨论】:

【参考方案2】:

为什么要将日期转换为日期?那没有意义。你可以这样做:

select '1'
from Dual
where date '2018-04-11' between sysdate - 14 and sysdate;

请注意,这也使用 date 关键字作为日期常量。

这是一个说明解决方案的rextester。请注意,这将在不到两周的时间内停止工作。

【讨论】:

这没有回答 OP 的问题“为什么它没有给出预期的结果?”。是的,它告诉他们可以做其他事情,但没有解释为什么他们的查询给出了意外的输出。

以上是关于使用 sysdate 时的 Oracle SQL,为啥它没有给出预期的结果的主要内容,如果未能解决你的问题,请参考以下文章

sql server to oracle

Oracle Apex 日期选择器行为异常

在 oracle SQL 中比较 DATE 和 SYSDATE 时,他们考虑时间吗?

oracle的sysdate和linux系统date时间不一致

在 Oracle 中插入后触发插入 sysdate

Oracle SYSDATE 输入数据类型