我正在使用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 ”。
有人能弄清楚吗,我想我缺少某种模式了
答案 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;