你说过你有日期格式MM/DD/YYYY
和MM/DD/YYYY HH:MI:SS AM
,而没有日期MM/DD/YYYY HH24:MI:SS
。您收到的错误消息表明您弄错了;“小时必须在 1 到 12 之间”表示您至少有一行以 24 小时格式显示时间。或者,可能是一些根本无法识别的时间。
将结构化数据(date
在本例中为 a)存储在自由文本字段中作为 avarchar2
而不是正确的数据类型的问题在于,您可以在其中获取任何旧垃圾,并且您依赖于应用程序验证数据,因为它是输入 - 根据您现在所看到的,这似乎没有做。嗯,主要问题之一,还有其他问题,包括性能影响。
尝试挽救数据的唯一方法是编写一个尝试多次转换的函数,并且仅在它有有效的东西或用完选项时才返回。可能是这样的:
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'