使用RegexLike检查Oracle SQL中的特定日期格式

时间:2019-04-18 06:31:40

标签: sql regex oracle

我正在使用oracle数据集成器作为ETL工具来加载数据,有一列作为源,其格式为 YYYYMMDD ,例如:20190418。我想查询该表以标识所有不符合20190418或 YYYYMMDD 格式的记录。 附言该列为 varchar2 数据类型。

我已经尝试使用类似这样的东西:

SELECT  CASE WHEN NOT REGEXP_LIKE('20190418', '^\d{4}(0[1-9]|1[12])(0[1-9]|[12]\d|3[01])$') then '00000000' else '20190418' END FROM DUAL; 

这似乎可以识别出那些非法日期,但例如,它不适用于此日期:“ 20181023 ”。

有人能弄清楚吗,我想我缺少某种模式了

3 个答案:

答案 0 :(得分:2)

我会提出一个函数而不是正则表达式,会更容易。

CREATE OR REPLACE FUNCTION Verify_date_number(inNumber IN NUMBER) RETURN VARCHAR2 AS        
    res DATE;
BEGIN   
    res := TO_DATE(inNumber, 'fxYYYYMMDD');       
    RETURN TO_CHAR(res, 'YYYYMMDD');       
EXCEPTION    
    WHEN OTHERS THEN        
        RETURN '00000000';
END;

如果您正在运行Oracle 12.2,则还可以使用VALIDATE_CONVERSION

SELECT
   CASE VALIDATE_CONVERSION('20190418' AS DATE, 'fxYYYYMMDD')
   WHEN 1 THEN '20190418'
   ELSE '00000000'
   END
FROM dual;

答案 1 :(得分:1)

使用PL / SQL可能是更好的选择

declare
   v_date     date;
begin
  for c in
  (
   select '20190418' as date_str from dual union all
   select '20191804' from dual union all
   select '201904187' from dual
  )
  loop
    begin    
       v_date := to_date(c.date_str,'yyyymmdd');    
       dbms_output.put_line(c.date_str);
      exception when others then null;   
    end;    
  end loop;  
end;  

仅提供格式正确的数据作为输出。在上述情况下,    仅20190418

对于20191804,我们将获得ORA-01843: not a valid month

对于201904187,我们将获得ORA-01830: date format picture ends before converting entire input string

错误

答案 2 :(得分:0)

您可以尝试以下一种方法:

SELECT a.*, b.*
FROM tblA a
LEFT JOIN tblB b
    ON b.op_code REGEXP CONCAT('[[:<:]]', a.op_code, '[[:>:]]');

结果:

with tab as(
  select '20190418' as dat from dual union all
  select '20181023' as dat from dual union all  
  select '20181123' as dat from dual union all  
  select '20181223' as dat from dual union all  
  select '20181201' as dat from dual union all  
  select '20181209' as dat from dual union all  
  select '20181210' as dat from dual union all  
  select '20181229' as dat from dual union all  
  select '20181231' as dat from dual union all  
  select '20181232' as dat from dual union all    
  select '20181200' as dat from dual union all  
  select '20191418' as dat from dual 
)
SELECT  CASE WHEN NOT REGEXP_LIKE(dat, '^\d{4}(0[1-9]|(1[0-2]))(0[1-9]|[1-2][0-9]|3[0-1])$') then '00000000' else dat END  as dat

FROM tab;