Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

oracle - mengonversi banyak format tanggal menjadi satu tanggal yang diformat

Jika Anda memiliki gagasan yang baik tentang semua kemungkinan format tanggal, mungkin lebih mudah menggunakan kekerasan:

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;
/

Ketahuilah bahwa Oracle versi modern cukup memaafkan dengan konversi tanggal. Fungsi ini menangani tanggal dalam format yang tidak ada dalam daftar, dengan beberapa konsekuensi menarik:

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> 

Yang menunjukkan batas pembersihan data otomatis dalam menghadapi aturan integritas data yang lemah. Upah dosa adalah data yang rusak.

@AlexPoole mengangkat masalah penggunaan 'RR' format. Elemen dari topeng tanggal ini diperkenalkan sebagai kludge Y2K. Agak menyedihkan bahwa kita masih mendiskusikannya hampir dua dekade memasuki Milenium baru.

Bagaimanapun, masalahnya adalah ini. Jika kita melemparkan string ini '161225' sampai tanggal berapa abad itu? Nah, 'yymmdd' akan memberikan 2016-12-15 . Cukup adil, tapi bagaimana dengan '991225' ? Seberapa besar kemungkinan tanggal yang kita inginkan adalah 2099-12-15 ? Di sinilah 'RR' format ikut bermain. Pada dasarnya default abad:angka 00-49 default ke 20, 50-99 default ke 19. Jendela ini ditentukan oleh masalah Y2K:pada tahun 2000 kemungkinan besar '98 mengacu pada masa lalu baru-baru ini daripada waktu dekat, dan logika serupa diterapkan pada '02 . Oleh karena itu, titik tengah tahun 1950. Perhatikan bahwa ini adalah titik tetap bukan jendela geser. Saat kita melangkah lebih jauh dari tahun 2000, titik pivot itu menjadi kurang berguna. Cari tahu lebih lanjut.

Bagaimanapun, poin kuncinya adalah bahwa 'RRRR' tidak cocok dengan format tanggal lain:to_date('501212', 'rrrrmmdd') hurls ora-01843:bukan bulan yang valid. So, use 'RR'and test for it before using 'YYYY'`. Jadi fungsi saya yang direvisi (dengan beberapa merapikan) terlihat seperti ini:

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;
/

Poin kuncinya tetap:ada batasan seberapa pintar kita dapat membuat fungsi ini dalam hal menafsirkan tanggal, jadi pastikan Anda memimpin dengan yang paling cocok. Jika menurut Anda sebagian besar string tanggal Anda cocok dengan hari-bulan-tahun, letakkan yang pertama; Anda masih akan mendapatkan beberapa pemeran yang salah tetapi lebih sedikit jika Anda memimpin dengan tahun-bulan-hari.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. ODP.NET Oracle.ManagedDataAccess menyebabkan file sesi jaringan ORA-12537 berakhir

  2. Cara mencetak beberapa laporan dengan barcode \ atau beberapa barcode dalam satu laporan

  3. Cara membuat batasan bukan nol di Oracle

  4. ORA-00933:Perintah SQL tidak berakhir dengan benar

  5. Jaring Pengaman