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

Làm thế nào để quản lý tốt nhất các giá trị tra cứu lịch sử trong cơ sở dữ liệu?

Có một kỹ thuật được gọi là tạo phiên bản đã tồn tại trong nhiều năm nhưng phần lớn không thể hoạt động được vì một số lý do. Tuy nhiên, có một kỹ thuật tương tự mà tôi gọi là Version Normal Form mà tôi thấy rất hữu ích. Đây là một ví dụ sử dụng bảng Nhân viên.

Đầu tiên, bảng tĩnh được tạo. Đây là bảng thực thể chính và nó chứa dữ liệu tĩnh về thực thể. Dữ liệu tĩnh là dữ liệu dự kiến ​​sẽ không thay đổi trong suốt thời gian tồn tại của thực thể, chẳng hạn như ngày sinh.

create table Employees(
  ID        int  auto_generated primary key,
  FirstName varchar( 32 ),
  Hiredate  date not null,
  TermDate  date,            -- last date worked
  Birthdate date,
  ...              -- other static data
);

Điều quan trọng là nhận ra có một mục nhập cho mỗi nhân viên, giống như với bất kỳ bảng nào như vậy.

Sau đó, bảng phiên bản được liên kết. Điều này thiết lập mối quan hệ 1 m với bảng tĩnh vì có thể có một số phiên bản cho một nhân viên.

create table Employee_versions(
  ID         int   not null,
  EffDate    date  not null,
  char( 1 )  IsWorking not null default true,
  LastName   varchar( 32 ),    -- because employees can change last name
  PayRate    currency not null,
  WorkDept   int   references Depts( ID ),
  ...,              -- other changable data
  constraint PK_EmployeeV primary key( ID, EffDate )
);

Trong bảng phiên bản, lưu ý có ngày có hiệu lực nhưng không có trường không còn hiệu lực phù hợp. Điều này là do khi một phiên bản có hiệu lực, nó vẫn có hiệu lực cho đến khi được thay thế bằng phiên bản tiếp theo. Sự kết hợp giữa ID và EffDate phải là duy nhất để không thể có hai xác minh cho cùng một nhân viên đang hoạt động cùng một lúc, cũng như không thể có khoảng cách giữa thời điểm một phiên bản kết thúc và khi phiên bản tiếp theo bắt đầu.

Hầu hết các truy vấn sẽ muốn biết phiên bản hiện tại của dữ liệu nhân viên. Điều này được cung cấp bằng cách tham gia hàng tĩnh cho nhân viên với phiên bản hiện có hiệu lực. Điều này có thể được tìm thấy với truy vấn sau:

select  ...
from    Employees e
join    Employee_versions v1
    on  v1.ID = e.ID
    and v1.EffDate =(
        select  Max( v2.EffDate )
        from    EmployeeVersions v2
        where   v2.ID = v1.ID
            and v2.EffDate <= NOW()
    )
where  e.ID = :EmpID;

Điều này trả về một và chỉ một phiên bản đã bắt đầu trong quá khứ gần đây nhất. Sử dụng bất đẳng thức <=trong kiểm tra ngày (v2.EffDate <= NOW() ) cho phép các ngày có hiệu lực trong tương lai. Giả sử bạn biết một nhân viên mới sẽ bắt đầu vào ngày đầu tiên của tháng tới hoặc dự kiến ​​tăng lương vào ngày 13 của tháng tiếp theo, dữ liệu này có thể được chèn trước thời hạn. Các mục nhập "được tải trước" như vậy sẽ bị bỏ qua.

Đừng để truy vấn con đến với bạn. Tất cả các trường tìm kiếm đều được lập chỉ mục nên kết quả khá nhanh.

Có rất nhiều sự linh hoạt với thiết kế này. Truy vấn trên trả về dữ liệu mới nhất của tất cả nhân viên, hiện tại và quá khứ. Bạn có thể kiểm tra TermDate lĩnh vực để chỉ có được nhân viên hiện tại. Trên thực tế, vì nhiều nơi trong ứng dụng của bạn sẽ chỉ quan tâm đến thông tin hiện tại của nhân viên hiện tại, nên truy vấn đó sẽ tạo ra một cái nhìn tốt (bỏ qua where cuối cùng mệnh đề). Không cần ứng dụng biết các phiên bản như vậy tồn tại.

Nếu bạn có một ngày cụ thể và bạn muốn xem dữ liệu có hiệu lực vào thời điểm đó, hãy thay đổi v2.EffDate <= NOW() trong truy vấn con tới v2.EffDate <= :DateOfInterest .

Bạn có thể tìm thêm thông tin chi tiết trong bản trình bày slide tại đây và một tài liệu chưa hoàn chỉnh tại đây.

Để thể hiện một chút khả năng mở rộng của thiết kế, hãy lưu ý rằng có một IsWorking chỉ báo trong bảng phiên bản cũng như ngày kết thúc trong bảng tĩnh. Khi một nhân viên rời công ty, ngày cuối cùng được chèn vào bảng tĩnh và một bản sao của phiên bản mới nhất với IsWorking đặt thành false được chèn vào bảng phiên bản.

Việc nhân viên rời bỏ công ty một thời gian rồi được thuê lại là điều khá phổ biến. Chỉ với ngày trong bảng tĩnh, mục nhập có thể được kích hoạt lại chỉ bằng cách đặt ngày đó trở lại NULL. Nhưng một truy vấn "nhìn lại" bất kỳ lúc nào khi người đó không còn là nhân viên sẽ trả về một kết quả. Sẽ không có dấu hiệu nào cho thấy họ đã rời công ty. Nhưng một phiên bản có IsWorking =false khi rời công ty và IsWorking =true khi trở lại công ty sẽ cho phép kiểm tra giá trị đó tại thời điểm quan tâm và bỏ qua nhân viên khi họ không còn là nhân viên ngay cả khi họ quay lại sau đó.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Liệt kê tất cả các trình kích hoạt trong Cơ sở dữ liệu Oracle

  2. Cách tìm bảng nơi thống kê bị khóa

  3. Tổng hợp kết nối ODP.NET:Cách biết kết nối đã được sử dụng hay chưa

  4. Sự khác biệt giữa USER () và SYS_CONTEXT ('USERENV', 'CURRENT_USER') là gì?

  5. Lỗi SQL:ORA-02291:ràng buộc toàn vẹn