日期范围比较

Date range comparison off-by-one

提问人:Pasi Savolainen 提问时间:6/29/2022 更新时间:6/29/2022 访问量:48

问:

Oracle 19c 中有一个包含列的表。查询不会选取值为“2000-01-01”的行DATE abc

select abc from t where abc <= DATE '2000-01-01'

如果我将查询修改为

select abc from t where abc < DATE '2000-01-01' + interval '1' day

显示的值(在 DBeaver、VSCode + Oracle Dev Tools 和 Oracle SQL Developer 中)始终为“2000-01-01”。

Oracle 日期 比较

评论

0赞 Olivier Jacot-Descombes 6/29/2022
修改后的查询是正确的,因为它确实考虑了日期/时间,包括时间部分。例如,它还将返回一个日期,例如 but not .这不是一个一分之一的问题。这是一个时间部分问题。2000-01-01 23:59:592000-01-02 00:00:00

答:

2赞 Pasi Savolainen 6/29/2022 #1

问题

Oracle 还存储插入/复制数据的时间部分,虽然它并不总是显示,但无论输出数据如何,它都会影响查询。

您可以通过查询来注意到它:

select to_char(abc, 'YYYY-MM-DD hh24:MI:ss') from t 
where trunc(abc) <= date '2000-01-01'

缓解

  • 使用可比较的日期(您正在搜索)作为变量并添加到其中。请注意,要调整您的比较限制,请使用而不是为了不意外地找到第二天的物品。+ interval '1' day<<=00:00:00
  • 不要使用 or ,它可能会破坏指数表现'trunc(abc)to_char(abc ..)
  • 添加到 SQL 编辑器启动脚本。ALTER SESSION SET nls_date_format='YYYY-MM-DD HH24:MI:SS';
1赞 MT0 6/29/2022 #2

在 Oracle 中,a 是一种二进制数据类型,由 7 个字节组成,分别表示:世纪、世纪年、月、日、小时、分钟和秒。它总是有这 7 个字节,并且从不以任何特定的(人类可读的)格式存储。DATE

显示的值(在 DBeaver、VSCode + Oracle Dev Tools 和 Oracle SQL Developer 中)始终为“2000-01-01”。

您看到的是客户端应用程序接收二进制值并试图提供帮助,并将二进制值显示为字符串;但是,客户端应用程序的默认格式是 并且不显示日期的时间部分。这并不意味着时间组件不存在,仅表示它不显示。DATEYYYY-MM-DD

您需要做的是进入首选项并更改客户端应用程序格式化日期的方式。

在 SQL Developer 中,可以使用:

ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';

这将设置当前会话的格式。或者,您可以进入并设置“日期格式”字段,该字段将设置当前会话和您从该客户端创建的任何未来会话的首选项。 Tool > Settings > Database > NLSYYYY-MM-DD HH24:MI:SS

您可以执行类似操作并更改大多数(所有)客户端应用程序中的设置。


select abc from t where abc <= DATE '2000-01-01'

等同于:

select abc from t where abc <= TIMESTAMP '2000-01-01 00:00:00'

它不会匹配介于 和 之间的行,但客户端应用程序不显示时间组件,因此您无法看到这些行具有非午夜时间组件,因此不应匹配。abc2000-01-01 00:00:012000-01-01 23:59:59

如果这样做:

select abc from t where abc < DATE '2000-01-01' + interval '1' day

然后,它将匹配这些行,因为它将匹配当天的整个 24 小时时段。