在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 use
to_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 )
由于您的 todate
是 date
您的问题源于列值从日期到 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)
我有一个 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 use
to_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 )
由于您的 todate
是 date
您的问题源于列值从日期到 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)