日期格式:无效的月份

时间:2013-10-16 15:49:54

标签: sql oracle date between

我的数据格式低于

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'

这不起作用。任何人都可以建议我应该怎么做以获得这两个日期之间的日期?

3 个答案:

答案 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/YYYYMM/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'