sql >> Database teknologi >  >> RDS >> Oracle

oracle - konverter mange datoformater til en enkelt formateret dato

Hvis du har en god idé om alle de mulige datoformater, kan det være lettere at bruge brute force:

create or replace function clean_date
    ( p_date_str in varchar2)
    return date
is
    l_dt_fmt_nt sys.dbms_debug_vc2coll := sys.dbms_debug_vc2coll
        ('DD-MON-YYYY', 'DD-MON-YY', 'DD-MM-YYYY', 'MM-DD-YYYY', 'YYYY-MM-DD'
         , 'DD/MM/YYYY', 'MM/DD/YYYY', 'YYYY/MM/DD', 'DD/MM/YY', 'MM/DD/YY');
    return_value date;
begin
    for idx in l_dt_fmt_nt.first()..l_dt_fmt_nt.last()
    loop
        begin
            return_value := to_date(p_date_str, l_dt_fmt_nt(idx));
            exit;
        exception
             when others then null;
        end;
    end loop;
    if return_value is null then
        raise no_data_found; 
    end if;
    return return_value;
exception
    when no_data_found then
        raise_application_error(-20000, p_date_str|| ' is unknown date format');
end clean_date;
/

Vær opmærksom på, at moderne versioner af Oracle er ret tilgivende med datokonvertering. Denne funktion håndterede datoer i formater, der ikke er på listen, med nogle interessante konsekvenser:

SQL> select  clean_date('20160817') from dual;

CLEAN_DAT
---------
17-AUG-16

SQL> select  clean_date('160817') from dual;

CLEAN_DAT
---------
16-AUG-17

SQL> 

Hvilket demonstrerer grænserne for automatiseret datarensning i lyset af slappe dataintegritetsregler. Syndens løn er korrupte data.

@AlexPoole rejser spørgsmålet om at bruge 'RR' format. Dette element i datomasken blev introduceret som en Y2K kludge. Det er ret deprimerende, at vi stadig diskuterer det næsten to årtier inde i det nye årtusind.

Under alle omstændigheder er problemet dette. Hvis vi caster denne streng '161225' til en dato, hvilket århundrede har den? Nå, 'yymmdd' vil give 2016-12-15 . Fair nok, men hvad med '991225' ? Hvor sandsynligt er det, at den dato, vi virkelig ønsker, er 2099-12-15 ? Det er her 'RR' format kommer i spil. Grundlæggende angiver det århundredet som standard:tallene 00-49 er standard til 20, 50-99 som standard til 19. Dette vindue blev bestemt af Y2K-problemet:i 2000 var det mere sandsynligt, at '98 henvist til den seneste fortid end den nærmeste fremtid, og lignende logik anvendt på '02 . Derfor halvvejs i 1950. Bemærk, at dette er et fast punkt ikke et skydevindue. Efterhånden som vi bevæger os længere fra år 2000, jo mindre nyttigt bliver det omdrejningspunkt. Få mere at vide.

Uanset hvad, det vigtigste er, at 'RRRR' ikke spiller godt sammen med andre datoformater:to_date('501212', 'rrrrmmdd') hurls ora-01843:ikke en gyldig måned. So, use 'RR'and test for it before using 'ÅÅÅÅ'. Så min reviderede funktion (med lidt oprydning) ser således ud:

create or replace function clean_date
    ( p_date_str in varchar2)
    return date
is
    l_dt_fmt_nt sys.dbms_debug_vc2coll := sys.dbms_debug_vc2coll
        ('DD-MM-RR', 'MM-DD-RR', 'RR-MM-DD', 'RR-DD-MM'
         , 'DD-MM-YYYY', 'MM-DD-YYYY', 'YYYY-MM-DD', 'YYYY-DD-MM');
    return_value date;
begin
    for idx in l_dt_fmt_nt.first()..l_dt_fmt_nt.last()
    loop
        begin
            return_value := to_date(p_date_str, l_dt_fmt_nt(idx));
            exit;
        exception
             when others then null;
        end;
    end loop;
    if return_value is null then
        raise no_data_found; 
    end if;
    return return_value;
exception
    when no_data_found then
        raise_application_error(-20000, p_date_str|| ' is unknown date format');
end clean_date;
/

Nøglepunktet forbliver:Der er en grænse for, hvor smart vi kan lave denne funktion, når det kommer til fortolkning af datoer, så sørg for, at du leder med den bedste pasform. Hvis du synes, at de fleste af dine datesnore passer til dag-måned-år, så sæt det først; du vil stadig få nogle forkerte afstøbninger, men mindre end hvis du leder med år-måned-dag.



  1. MySQL – MariaDB – Skrivning af den allerførste lagrede procedure

  2. Sådan opretter du en underformular ud fra en tabel i Access 2016

  3. Kan du bruge et alias i WHERE-sætningen i mysql?

  4. IKKE I valg med NULL-værdier