我有这个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是一个有效的月份,但如果我尝试
当我尝试将其更改为预期的日期格式时:
m/dd/yy
mm/dd/yyyy
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
......它有效,但似乎我没有正确处理这个问题。
我做错了什么?此外,如果有更好,更有效的方式,我会全力以赴。
答案 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} })。
请尝试这样做(假设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
,那么您需要查看列中存储值的日期格式,并相应地格式化查询。
小于或等于(&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_dateDATE '2015-09-27'
来自oracle文档:
ANSI日期文字不包含时间部分,必须指定 正是这种格式(&#39; YYYY-MM-DD&#39;)。