1

我有这个 Oracle 数据库,它有一个格式如下的日期列表:mm/dd/yy 0:00:00 AM/PM(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

我收到此错误: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/2015, 和之间获取数据9/26/2015。不是应该从 2015 年 8 月 27 日到 2015 年 9 月 27 日吗?

所以我把最后一行改成这样:

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

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

我究竟做错了什么?此外,如果有更好、更有效的方法来做到这一点,我会全力以赴。

4

2 回答 2

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 位数的年份,因此您应该使用yyyy)时,您应该始终指定日期格式。

试试这个(假设DATELIST是一个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是,VARCHAR2那么您需要查看值存储在列中的日期格式,并相应地格式化查询。

小于或等于 (<=) 运算符仅在 2015 年 8 月 27 日到 2015 年 9 月 26 日之间获取数据。不是应该从 2015 年 8 月 27 日到 2015 年 9 月 27 日吗?

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

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我认为您的问题与数据类型 DATELIST的隐藏时间部分有关。

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

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

WHERE DATELIST >= TO_DATE('09/26/2015', 'MM/DD/RRRR')
  AND DATELIST <= TO_DATE('09/27/2015', 'MM/DD/RRRR');

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

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

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');

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

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'));

虽然这会破坏 DATELIST 列上的任何索引。

于 2015-10-01T15:07:43.723 回答
0

而不是使用 to_date 使用 ANSI 日期文字:

DATE '2015-09-27'

来自 oracle 文档:

ANSI 日期文字不包含时间部分,并且必须完全以这种格式('YYYY-MM-DD')指定。

于 2015-10-01T15:26:30.203 回答