【问题标题】:Sql queries regarding dates关于日期的 Sql 查询
【发布时间】:2017-05-03 14:49:16
【问题描述】:
select sysdate
from dual;
日期 -------- 2017 年 5 月 3 日
select sysdate -1 
from dual;
日期 -------- 2017 年 5 月 2 日 ===============

如果运行下面的sql查询

select TO_DATE('01-DEC-15','DD-MON-YYYY') - 1
FROM DUAL;

我得到了答案
2015 年 11 月 30 日

===== 任何机构都可以帮助我理解这种行为吗?

【问题讨论】:

  • 这似乎是不言自明的。哪部分让您感到不安?
  • 一切都是一致的。 -1 在日期前一天为您提供服务。问题出在哪里?
  • 请注意,SYSDATE 也有一个时间组件(您的前端程序没有显示...在设置中的某个位置进行控制)。 “-1”正好减去 24 小时; sysdate - 1 将具有与 sysdate 相同的时间组件。您的 to_date(....) 示例还具有时间组件(在 Oracle 中没有“纯”日期,没有时间组件);但是,在这种情况下,由于您没有指定具体时间,因此默认为 00:00:00。
  • 另外请注意,您的第三个示例是在 0015 年,而不是 2015 年...当您给出 2 位年份和 4 位数字时,您是否在问为什么该查询仍然有效格式?
  • 仅供参考:trunc(sysdate) 获取删除时间部分的日期。

标签: sql oracle sysdate


【解决方案1】:

文档有a section on datetime/interval arithmetic。添加到日期或从日期中减去的数字被视为一天的一小部分:

例如,SYSDATE + 1 是明天。 SYSDATE - 7 是一周前。 SYSDATE + (10/1440) 距离现在十分钟

正如@mathguy 所指出的,Oracle 中的所有日期都有一个时间组件,sysdate 有当前服务器时间。如果显示日期/时间的完整值,您可以看到发生了什么。您可以使用 to_char() 和合适的格式明确地做到这一点,但为了简洁起见,我将更改我的会话 NLS 设置:

alter session set nls_date_format = 'SYYYY-MM-DD HH24:MI:SS';

select sysdate, sysdate - 1
from dual;

SYSDATE              SYSDATE-1           
-------------------- --------------------
 2017-05-03 16:17:47  2017-05-02 16:17:47

两者都显示相同的时间,但在不同的日子。

你可以truncate a date来降低它的精度;默认情况下,trunc(sysdate) 会将时间元素归零,因此它变为今天的午夜,而不是当前时间。

您的第三个示例稍微有趣一些,因为您使用了不匹配的值和格式掩码;使用 2 位数的年份和 4 位数的 YYYY 掩码,年份不会像您预期的那样结束:

select to_date('01-DEC-15','DD-MON-YYYY'), to_date('01-DEC-15','DD-MON-YYYY') - 1
from dual;

TO_DATE('01-DEC-15', TO_DATE('01-DEC-15',
-------------------- --------------------
 0015-12-01 00:00:00  0015-11-30 00:00:00

这可能不是你想要的。 RRRR 掩码更宽容,如手册中所述:

select to_date('01-DEC-15','DD-MON-RRRR'), to_date('01-DEC-15','DD-MON-RRRR') - 1
from dual;

TO_DATE('01-DEC-15', TO_DATE('01-DEC-15',
-------------------- --------------------
 2015-12-01 00:00:00  2015-11-30 00:00:00

但最好还是提供完整的 4 位数年份:

select to_date('01-DEC-2015','DD-MON-YYYY'), to_date('01-DEC-2015','DD-MON-YYYY') - 1
from dual;

TO_DATE('01-DEC-2015 TO_DATE('01-DEC-2015
-------------------- --------------------
 2015-12-01 00:00:00  2015-11-30 00:00:00

或者更简单,使用date literal:

select date '2015-12-01', date '2015-12-01' - 1
from dual;

DATE'2015-12-01'     DATE'2015-12-01'-1  
-------------------- --------------------
 2015-12-01 00:00:00  2015-11-30 00:00:00

这也避免了日期问题语言'APR' 不会在语言 - 特别是 NLS_DATE_LANGAUGE - 不是英语的会话中被识别(除非它巧合地是另一种语言的公认缩写,但几个月仍然会失败)。最好使用月份数字。如果您必须使用名称或缩写,您可以使用to_date() 的可选第三个参数指定它们使用的语言。但是,如果您不从字符串变量转换,文字仍然更容易。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-21
    • 2021-01-04
    • 1970-01-01
    • 2018-10-17
    • 2021-02-17
    • 1970-01-01
    相关资源
    最近更新 更多