如何从 Oracle 中的当前时间获得 24 小时倒退时间

How to get 24 hours back time from current time in Oracle

我的 Oracle 数据库中有一列以下列格式记录用户的创建时间 30-NOV-20 11.49.11.000000000 AM(TIMESTAMP(6) 格式)。 我想做的是 select 所有创建时间比当前时间早 24 小时的记录 所以我要做的是从当前时间减去 1 并进行比较。但是当我减去 1 时,它 returns 只有日期。

select * from user where created_date < SYSTIMESTAMP-1

dbms_output.put_line (SYSTIMESTAMP-1);-->29-NOV-20

缺少时间部分,这让我无法与 table 中创建的时间进行比较 请帮我完成这个任务。

如果您从 date 数据类型(例如 sysdate)中减去 1,它会让您倒退一天。但是,如果您从 timestamp 数据类型值中减去它,Oracle 会将其转换为 date 和 return 日期(此外,它将被截断)。

参见以下示例:

SQL> select
  2    systimestamp val1,
  3    systimestamp - 1 val2,
  4    --
  5    systimestamp - interval '1' day val3
  6  from dual;

VAL1
-----------------------------------------------------
VAL2
--------
VAL3
-----------------------------------------------------
30.11.20 09:55:01,439352 +01:00
29.11.20
29.11.20 09:55:01,439352000 +01:00


SQL>

所以,你应该做的是减去一个间隔,即

select *
from user
where created_date < systimestamp - interval '1' day;

您可以将其用作 (SYSDATE, -1)。 另外,如果要搜索24小时内的新记录,应该是"created_date> = (sysdate-1)".

一半的问题是,无论使用什么客户端程序来显示值,都使用 作为其领土,并且默认格式设置为 DD-MON-RR.

您可以更改 NLS_DATE_FORMATNLS_TIMESTAMP_FORMAT 会话参数,这将(假设您的客户端程序使用它们而不是某些内部设置)为您提供您期望的输出:

ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF9';
ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF9TZR';

然后

SELECT SYSDATE, SYSTIMESTAMP FROM DUAL;

输出(取决于您的系统时区):

SYSDATE             | SYSTIMESTAMP                       
:------------------ | :----------------------------------
2020-11-30 10:12:22 | 2020-11-30 10:12:22.476282000+00:00

如果您使用 SYSTIMESTAMP-1,则 Oracle 不支持从 TIMESTAMP [WITH TIME ZONE] 数据类型中减去 NUMBER 数据类型,但它支持从中减去 NUMBER 数据类型DATE 数据类型并将执行从 TIMESTAMPDATE 的隐式转换,以便查询有效。

例如:

SELECT SYSDATE - 1, SYSTIMESTAMP - 1, SYSTIMESTAMP - INTERVAL '1' DAY FROM DUAL;

输出:

SYSDATE-1           | SYSTIMESTAMP-1      | SYSTIMESTAMP-INTERVAL'1'DAY        
:------------------ | :------------------ | :----------------------------------
2020-11-29 10:24:02 | 2020-11-29 10:24:02 | 2020-11-29 10:24:02.651735000+00:00

您可以看到,在中间列中,SYSTIMESTAMP-1 给出了与 SYSDATE-1 相同的输出,但在右侧列中,减去一个间隔确保了 TIMESTAMP WITH TIME ZONE 数据类型是维护。

所以你的查询:

SELECT * FROM user WHERE created_date <  SYSTIMESTAMP-1

有效:

SELECT * FROM user WHERE created_date <  CAST( SYSTIMESTAMP AS DATE )-1

它将具有完全相同的年、月、日、小时、分钟和(整数)秒组件,但会丢失 SYSTIMESTAMP 中的小数秒和时区信息。

如果您的列没有时区数据并且小数秒的精度水平对您来说无关紧要,那么您的查询就可以正常工作。

但是,如果您想保留时区 and/or 小数秒信息,那么您可以使用:

SELECT * FROM user WHERE created_date <  SYSTIMESTAMP - INTERVAL '1' DAY;

但是,如果 created_dateDATE 列,您可能需要:

SELECT * FROM user WHERE created_date <  SYSDATE - INTERVAL '1' DAY;

SELECT * FROM user WHERE created_date <  SYSDATE - 1;

db<>fiddle here