在Oracle中检索日期范围内的数据

Retrieve data within a date range in Oracle

我有一个 table tbldeptdivision 如下:

ID  DEPTID  DIVISIONID  FROMDATE    TODATE      REMARKS 
--- ------- ----------- ----------- ----------- --------
21  21      5           31-AUG-99   01-JAN-80   NULL

我有疑问

select *
  from tbldeptdivision
 where deptid = 21
   and trunc(sysdate) between to_date(fromdate,'dd-Mon-yyyy')
                          and to_date(todate,'dd-mon-yyyy');

它returns我没有价值。谁能说为什么? '31-AUG-99' 实际上是 '31-AUG-1999''01-JAN-80' 实际上是 '01-JAN-2080'。确切的查询是什么?

假设 FROMDATE/TODATE 数据类型是 varchar2 然后当你做 to_date;

select to_date('01-JAN-80','dd-mon-yyyy') from dual;
OutPut: January, 01 0080 00:00:00

所以不会是'01-JAN-2080'而是'01-JAN-0080'

即使 FROMDATE/TODATE 数据类型是 date 使用 to_date 也不是一个好主意;

create table t(c date);
insert into t select sysdate from dual;
select c, to_date(c,'dd-mon-yyyy') from t;

输出:

C                           TO_DATE(C,'DD-MON-YYYY')
August, 25 2015 10:55:36    August, 25 0015 00:00:00

年份仍然是 0015 而不是 2015

如果您的列数据类型是日期,则使用 trunc to get the日期部分don't useto_date`。

select * 
from tbldeptdivision
where deptid=21
and trunc(sysdate) between trunc(fromdate) 
and trunc(todate)

在 where 子句中对字段使用函数会降低生产速度。这是相同的逻辑,运行 会更快。

where fromdate <= trunc(sysdate)
and todate > trunc(sysdate )

由于您的 todatedate 您的问题源于列值从日期到 varchar 并返回到日期的无用转换:

to_date()VARCHAR 转换为 DATE 值。如果您传递给该函数的值是 already a DATE Oracle 将首先通过应用默认 NLS 格式将您的日期隐式转换为 varchar,然后将转换 that varchar 返回一个日期,再次应用默认的 NLS 格式。

在第一次(隐式)转换中,你失去了你所在年份的世纪,因此当 varchar 转换回 date

时,这是错误的

因此在您的情况下,由于调用 to_date(fromdate,'dd-Mon-yyyy')

完成了以下操作
  • todate 包含(实际)日期值:1980-01-30
  • 到 varchar 的隐式转换使得 '01-JAN-80'
  • 从 varchar 到日期的转换假设 80 年应该是 2080(同样基于 implicit 数据类型转换的规则)。

一般规则是:

不要在 DATE(或 TIMESTAMP)列上使用 to_date()

如果您需要去掉 DATE 列中的时间部分,请改用 trunc()

where trunc(sysdate) between trunc(fromdate) and trunc(todate)