我的数据格式低于
2003年10月29日
10/21/2003 7:26:00 AM在表格中
我希望比较'07 -14-2013'和'09 -15-2013'之间的日期。我编写了代码
'07 -14-2013 00:00:00 AM'和'之间的to_char(to_date(a.TEXT_VALUE,'DD-MM-YYYY HH:MI:SS AM'),'dd-mm-YYYY') 09-15-2013 00:00:00 AM'
这不起作用。任何人都可以建议我应该怎么做以获得这两个日期之间的日期?
答案 0 :(得分:5)
你的日子和月份都有所逆转。 美国人(也可能是其他国家)使用MM-DD-YYYY的符号:
to_char(to_date(a.TEXT_VALUE, 'MM-DD-YYYY HH:MI:SS AM'),'mm-dd-YYYY')
between '07-14-2013 00:00:00 AM' and '09-15-2013 00:00:00 AM'
答案 1 :(得分:1)
正如其他人所说,你真的不知道那个varchar字段中的什么,日期应该存储为日期(所以你可以用日期做所有美好的事情,比如比较它们,减去它们,得到日期范围等等......)。
因此,如果您的1条记录的日期无效,则to_date将会中断。但是,你说你只想抓住一个日期范围内的记录,你可能会忽略使用substr的日期的时间部分(并且仍然希望这些日子是有效的):
with date_strings as
(
select 1 as id, '01/31/2013' as dte_str from dual
union
select 2 as id, '02/01/2013 13:55:01' as dte_str from dual
union
select 3 as id, '02/28/2013 10:30:01 AM' as dte_str from dual
union
select 4 as id, '03/01/2013 11:15:01 AM' as dte_str from dual
)
select
id, dte_str, to_date(substr(dte_str, 1, 10), 'MM/DD/YYYY') as dte
from date_strings
where to_date(substr(dte_str, 1, 10), 'MM/DD/YYYY') between
to_date('02/01/2013', 'MM/DD/YYYY') and to_date('03/01/2013', 'MM/DD/YYYY')-1;
此示例抓取日期在2013年2月某处的行(如果您的字符串的MM / DD / YYYY部分无效,则会失败,例如02/29/2013) 。但至少你可以忽略时间格式的变化。
答案 2 :(得分:0)
您说您的日期格式为MM/DD/YYYY
和MM/DD/YYYY HH:MI:SS AM
,而日期格式为MM/DD/YYYY HH24:MI:SS
。您收到的错误消息表明您错了; '小时必须在1到12之间'表示您至少有一行时间为24小时格式。或者,可能,某些事情根本不是一个可识别的时间。
将结构化数据(本例中为date
)作为varchar2
而不是正确的数据类型存储在自由文本字段中的问题是,您可以在那里获取任何旧垃圾,并且您在输入时依赖于您的应用程序验证数据 - 根据您现在看到的情况,这似乎没有做到。嗯,其中一个主要问题,还有其他问题,包括性能影响。
尝试抢救数据的唯一方法是编写一个尝试多次转换的函数,只有当它有效时才会返回 - 或者用完选项。也许是这样的事情:
create or replace function clean_date(text_value varchar2) return date is
begin
begin
return to_date(text_value, 'MM/DD/YYYY HH24:MI:SS');
exception
when others then
null;
end;
begin
return to_date(text_value, 'MM/DD/YYYY HH:MI:SS AM');
exception
when others then
null;
end;
return null;
end clean_date;
/
这只是尝试两种格式,但您可以根据需要添加更多格式 - 任何获得null
的行都无法通过其尝试的任何格式进行转换。你需要对你测试它们的顺序要小心,以避免错误匹配的可能性。每个begin
/ exception
/ end
子块都在测试一种格式;捕获other
并不理想,但另一种方法是声明所有可能的日期格式异常,这些异常会很痛苦且容易出错。如果没有异常,则返回该日期值;如果有任何异常,那么它只会移动到下一个块以尝试下一个格式。
如果你有一些非常意外的事情,这也无济于事,如果你的英国格式的日期为DD/MM/YYYY
,则不会总是出错 - 如果日期和月份都小于13无法分辨哪个是哪个。
无论如何,你的过滤器可能会成为:
where trunc(clean_date(a.text_value))
between date '2013-07-14' and date '2013-09-15'
如果您愿意,可以将其转换回字符串,但仍然使用合理的日期格式进行比较:
where to_char(clean_date(a.text_value), 'YYYY-MM-DD')
between '2013-07-14' and '2013-09-15'