使用 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_FORMAT
与 DD-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 - 14
或 SYSDATE
格式为 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,为啥它没有给出预期的结果的主要内容,如果未能解决你的问题,请参考以下文章
在 oracle SQL 中比较 DATE 和 SYSDATE 时,他们考虑时间吗?