2013-04-01 57 views
0

我使用的是Oracle 11G,并且我有一个日期列(Var char 2),其中日期是手动输入到数据库中的,不幸的是很多时候输入的日期无效。我只想选择使用某种REGEXP LIKE语句有效的日期字段。以下是我想要选择的可能的有效格式。Oracle使用REGEXP验证日期字段

DATE 

JULY 31, 2009 
7/31/2009 
31-JUL-09 

任何不是这3种可能的格式我不想选择。有人可以帮助我想出一个REGEXP或其他方式来选择这些有效的日期格式。提前致谢。

+2

一个很好的理由,为什么日期应保存为** **日期而不是文字。 –

+0

您是否要求我们为您编写您的'REGEXP_LIKE'声明?这不是一个真正的问题,这是你可以弄清楚自己的东西,对吧?你已经知道你需要使用REGEXP_LIKE,所以不要懒惰写一个。 – Scotch

+0

苏格兰威士忌如果我知道如何在一个REGEXP_LIKE中为所有三种格式编写REGEXP我会自己做,但我似乎无法让它工作。感谢您的有用的输入... – swingard

回答

1

尝试PL/SQL而不是正则表达式。它会明显变慢,但会更安全,更容易维护和扩展。 您应该依靠Oracle格式模型正确执行此操作。我看到很多尝试使用正则表达式来验证这些信息,但我很少看到它正确完成。

如果你真的关心性能,真正的答案是修复你的数据模型。

代码和测试用例:

--Function to convert a string to a date, or return null if the format is wrong. 
create or replace function validate_date(p_string in string) return date is 
begin 
    return to_date(p_string, 'MONTH DD, YYYY'); 
exception when others then 
    begin 
     return to_date(p_string, 'MM/DD/YYYY'); 
    exception when others then 
     begin 
      return to_date(p_string, 'DD-MON-RR'); 
     exception when others then 
      return null; 
     end; 
    end; 
end; 
/

--Test individual values 
select validate_date('JULY 31, 2009') from dual; 
2009-07-31 
select validate_date('7/31/2009') from dual; 
2009-07-31 
select validate_date('31-JUL-09') from dual; 
2009-07-31 
select validate_date('2009-07-31') from dual; 
<null> 

简单性能测试:

--Create table to hold test data 
create table test1(a_date varchar2(1000)) nologging; 

--Insert 10 million rows 
begin 
    for i in 1 .. 100 loop 
     insert /*+ append */ into test1 
     select to_char(sysdate+level, 'MM/DD/YYYY') from dual connect by level <= 100000; 

     commit; 
    end loop; 
end; 
/

--"Warm up" the database, run this a few times, see how long a count takes. 
--Best case time to count: 2.3 seconds 
select count(*) from test1; 


--How long does it take to convert all those strings? 
--6 minutes... ouch 
select count(*) 
from test1 
where validate_date(a_date) is not null;