Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

oracle - chuyển đổi nhiều định dạng ngày tháng sang một ngày được định dạng duy nhất

Nếu bạn có ý tưởng tốt về tất cả các định dạng ngày tháng có thể có, thì việc sử dụng brute force có thể dễ dàng hơn:

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

Cần biết rằng các phiên bản hiện đại của Oracle khá dễ dàng với việc chuyển đổi ngày tháng. Hàm này xử lý ngày tháng ở các định dạng không có trong danh sách, với một số hậu quả thú vị:

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> 

Điều này chứng tỏ giới hạn của việc làm sạch dữ liệu tự động khi đối mặt với các quy tắc toàn vẹn dữ liệu lỏng lẻo. Tiền công của tội lỗi là dữ liệu bị hỏng.

@AlexPoole đặt ra vấn đề sử dụng 'RR' định dạng. Yếu tố này của mặt nạ ngày tháng được giới thiệu dưới dạng k bùn Y2K. Thật đáng buồn khi chúng ta vẫn đang thảo luận về nó trong gần hai thập kỷ về Thiên niên kỷ mới.

Dù sao, vấn đề là thế này. Nếu chúng ta truyền chuỗi này '161225' đến nay nó có từ thế kỷ nào? Chà, 'yymmdd' sẽ cung cấp cho 2016-12-15 . Khá ổn, nhưng '991225' thì sao ? Khả năng ngày chúng ta thực sự muốn là 2099-12-15 như thế nào ? Đây là nơi chứa 'RR' định dạng phát huy tác dụng. Về cơ bản, nó mặc định thế kỷ:số 00-49 mặc định là 20, 50-99 mặc định là 19. Cửa sổ này được xác định bởi sự cố Y2K:vào năm 2000, nhiều khả năng là '98 đề cập đến quá khứ gần đây hơn là tương lai gần và logic tương tự được áp dụng cho '02 . Do đó là nửa điểm của năm 1950. Lưu ý rằng đây là điểm cố định không phải là cửa sổ trượt. Khi chúng ta tiến xa hơn từ năm 2000, điểm xoay đó càng trở nên ít hữu ích hơn. Tìm hiểu thêm.

Dù sao, điểm mấu chốt là 'RRRR' không hoạt động tốt với các định dạng ngày khác:to_date('501212', 'rrrrmmdd') hurls ora-01843:không phải là một tháng hợp lệ . So, use 'RR' and test for it before using 'VẬY'. Vì vậy, chức năng đã sửa đổi của tôi (với một số thu dọn) trông như thế này:

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

Điểm mấu chốt vẫn là:có một giới hạn về mức độ thông minh mà chúng tôi có thể thực hiện chức năng này khi giải thích ngày tháng, vì vậy hãy đảm bảo rằng bạn dẫn đầu với sự phù hợp nhất. Nếu bạn nghĩ rằng hầu hết các chuỗi ngày của bạn phù hợp với ngày-tháng-năm, hãy đặt điều đó trước; bạn vẫn sẽ nhận được một số sai lầm nhưng ít hơn nếu bạn dẫn đầu với năm-tháng-ngày.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Trình điều khiển Oracle ODBC của bạn tải ứng dụng khách Oracle như thế nào?

  2. Cách ánh xạ một chuỗi thành chuỗi DB trong Hibernate

  3. Cách giải quyết ORA-29913 với bảng bên ngoài

  4. Cách xuất lược đồ cơ sở dữ liệu trong Oracle sang tệp kết xuất

  5. Đối chiếu không phân biệt trọng âm và chữ hoa chữ thường trong Oracle với LIKE