Oracle中的日期范围问题。如何以此格式正确获取日期范围?

时间:2015-10-01 14:39:03

标签: sql oracle sql-date-functions

我有这个Oracle数据库,它有一个这种格式的日期列表:mm/dd/yy 0:00:00 AM/PM(1表示1月,而不是01; 1表示当天,而不是01,依此类推)。

当我尝试查询时,例如:

select DATELIST from CORE.DATE_TEST
where to_date(DATELIST) >= to_date('8/27/2015', 'mm/dd/yy') AND to_date(DATELIST, 'mm/dd/yy') <= to_date('9/27/2015', 'mm/dd/yy');

它给了我以下错误:ORA-01843: not a valid month。我也看不出27是一个有效的月份,但如果我尝试

它会接受这个输入

当我尝试将其更改为预期的日期格式时:

  1. m/dd/yy
  2. mm/dd/yyyy
  3. m/d/yy
  4. 我收到此错误:ORA-01821: date format not recognized

    当我将其切换到dd/mm/yy时,它有点起作用,但不是真的;它给了我无效的结果。

    然而,这有效:

    select DATELIST from CORE.DATE_TEST
    where to_date(DATELIST) >= to_date('8/27/2015', 'mm/dd/yy') 
    

    PL / SQL脚本正在破坏以下内容:

    AND to_date(DATELIST, 'mm/dd/yy') <= to_date('9/27/2015', 'mm/dd/yy');
    

    当我用以下代码替换上面的代码时:

    SELECT to_date(DATELIST, 'dd/mm/yy') 
        FROM CORE.DATE_TEST
    WHERE DATELIST >= to_date('8/27/2015', 'mm/dd/yy')
        AND DATELIST <= to_date('9/27/2015', 'mm/dd/yy');
    

    它的工作速度快了一百万倍,但它无法正确解析日期范围。小于或等于(<=)运算符仅在8/27/20159/26/2015之间抓取数据。它不应该是2015年8月27日到2015年9月27日吗?

    所以我将最后一行更改为:

    AND DATELIST <= to_date('9/27/2015', 'mm/dd/yy') + 1
    

    ......它有效,但似乎我没有正确处理这个问题。

    我做错了什么?此外,如果有更好,更有效的方式,我会全力以赴。

2 个答案:

答案 0 :(得分:2)

您在原始问题中遇到了一些问题,我将尝试在此处解决部分或全部问题:

When I try a query such as:
select DATELIST from CORE.DATE_TEST
where to_date(DATELIST) >= to_date('8/27/2015', 'mm/dd/yy') AND to_date(DATELIST, 'mm/dd/yy') <= to_date('9/27/2015', 'mm/dd/yy');
It gives me the following error: ORA-01843: not a valid month

指定to_date(DATELIST)时未指定日期格式,因此默认为默认日期格式的NLS设置。每当使用TO_DATE时,您应始终指定日期格式以防止这种情况发生,并确保您的日期格式是明确的(并且您正在使用yy但是您指定的是4位数年份,因此您应该使用{{1} })。

请尝试这样做(假设yyyyDATELIST数据类型):

DATE

如果select TO_CHAR(DATELIST, 'DD-MON-YYYY HH24:MI:SS') -- Use whatever date format is clearest to you from CORE.DATE_TEST where DATELIST >= to_date('8/27/2015 00:00:00', 'mm/dd/yyyy hh24:mi:ss') AND DATELIST <= to_date('9/27/2015 23:59:59', 'mm/dd/yyyy hh24:mi:ss'); DATELIST,那么您需要查看列中存储值的日期格式,并相应地格式化查询。

  

小于或等于(&lt; =)运算符只是抓取数据   2015年8月27日至2015年9月26日期间。它不应该是8/27/2015   到2015年9月27日?

当您使用VARCHAR2并且不指定日期的时间部分时,小时,分钟和秒的默认值为00:00:00。如果您想要完整的日期范围,请尝试更明确:

TO_DATE

我怀疑,查询速度更快的原因是,SELECT to_date(DATELIST, 'dd/mm/yy hh24:mi:ss') FROM CORE.DATE_TEST WHERE DATELIST >= to_date('8/27/2015 00:00:00', 'mm/dd/yyyy hh24:mi:ss') AND DATELIST <= to_date('9/27/2015 23:59:59', 'mm/dd/yyyy hh24:mi:ss'); 列上有一个索引,当您使用DATELIST TO_DATE调用TO_DATE(DATELIST, 'mm/dd/yyyy')调用它时,它会失败}。

如果DATELIST的数据类型为DATE,请将其保留为VARCHAR2,如果它DATE,那么您会有一些额外的日期格式问题。

希望有所帮助

编辑:

我认为您的问题与WHERE DATELIST >= TO_DATE('09/26/2015', 'MM/DD/RRRR') AND DATELIST <= TO_DATE('09/27/2015', 'MM/DD/RRRR'); 数据类型DATELIST的隐藏时间部分有关。

如果你有价值: 09/27/2015 10:35:12

即使你不关心那个日期的10:35:12部分,它仍然存在。如果您然后尝试使用以下where子句:

WHERE DATELIST >= TO_DATE('09/26/2015 00:00:00', 'MM/DD/RRRR HH24:MI:SS')
  AND DATELIST <= TO_DATE('09/27/2015 23:59:59', 'MM/DD/RRRR HH24:MI:SS');

然后该值不会被拾取,因为它大于: 09/27/2015 00:00:00。

您需要将上限提高一天或指定时间部分,例如:

SELECT to_date(DATELIST, 'dd/mm/yy') as Date_Accessed 
  FROM CORE.DATE_TEST 
 WHERE (trunc(DATELIST) >= to_date('9/27/2015', 'mm/dd/yy')) 
   AND (trunc(DATELIST) <= to_date('9/30/2015', 'mm/dd/yy'));

EDIT2: 与OP合作,他说这有效:

str

虽然这会打败DATELIST专栏的任何索引。

答案 1 :(得分:0)

使用ANSI日期文字:

而不是使用to_date
DATE '2015-09-27'

来自oracle文档:

  

ANSI日期文字不包含时间部分,必须指定   正是这种格式(&#39; YYYY-MM-DD&#39;)。