问题的一半是用于显示值的任何客户端程序都将default date format 用于其领土,并且默认格式设置为DD-MON-RR。
您可以更改 NLS_DATE_FORMAT 和 NLS_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;
输出(取决于您的系统时区):
日期 |系统时间戳
:----------------- | :------------------------------------
2020-11-30 10:12:22 | 2020-11-30 10:12:22.476282000+00:00
如果您使用 SYSTIMESTAMP-1,则 Oracle 不支持从 TIMESTAMP [WITH TIME ZONE] 数据类型中减去 NUMBER 数据类型,但它支持从 DATE 数据类型中减去 NUMBER 数据类型,并将执行从 TIMESTAMP 隐式转换为 DATE 以便查询有效。
例如:
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 的小数秒和时区信息。
如果您的列没有时区数据,并且小数秒的精度级别对您来说并不重要,那么您的查询将充分发挥作用。
但是,如果您想保留时区和/或小数秒信息,则可以使用:
SELECT * FROM user WHERE created_date < SYSTIMESTAMP - INTERVAL '1' DAY;
但是,如果 created_date 是 DATE 列,您可能需要:
SELECT * FROM user WHERE created_date < SYSDATE - INTERVAL '1' DAY;
或
SELECT * FROM user WHERE created_date < SYSDATE - 1;
db小提琴here