【问题标题】:Retrieve data within a date range in Oracle在 Oracle 中检索日期范围内的数据
【发布时间】:2015-11-19 00:28:50
【问题描述】:

我有一个表 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');

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

【问题讨论】:

  • 标记您正在使用的技术
  • FROMDATE and TODATE 的数据类型是什么。 Date or varchar???
  • 我正在使用 oracle。数据类型是日期
  • 它不返回任何内容,因为它在两列中都假设 20 世纪? 1999 年到 1980 年之间什么都没有。
  • 您确定将 80 年的日期视为 2080 而不是 1980?我有疑问。没有人从千年虫“危机”中吸取教训吗?使用两位数表示年份是愚蠢的!

标签: sql oracle date between date-range


【解决方案1】:

假设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 thedate partdon't useto_date`。

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

【讨论】:

    【解决方案2】:

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

    to_date()VARCHAR 转换为 DATE 值。如果您传递给该函数的值 已经 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 年(再次基于 隐式 数据类型转换的规则)。

    一般规则是:

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

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

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

    【讨论】:

      【解决方案3】:

      在 where 子句中的字段上使用函数会减慢生产速度。这是相同的逻辑,并且会运行得更快。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-25
        • 1970-01-01
        • 2020-04-29
        • 1970-01-01
        相关资源
        最近更新 更多