quan hệ S_DURING; trong Bảng 1.4, thực tế ta đã dùng quy định gạch chân để chỉ
ra khoá đó nhƣ là một khoá chính đặc biệt. (Nhận thấy rằng bản thân {S#} không phải là một khoá dự tuyển, bởi vì có thể một nhà cung cấp đã chấm dứt hợp đồng và sau đó lại đƣợc ký lại vào một ngày sau đó – ví dụ: nhà cung cấp S2 trong Bảng 1.4). Do đo biến quan hệ S_DURING có thể đƣợc định nghĩa nhƣ sau:
VAR S_DURING RELATION
{S# S#, TENCONGTY NAME, TRANGTHAI INTEGER, DIACHI CHAR, DURING INTERVAL (DATE)}
KEY {S#, DURING}; /* không thích đáng*/
Tuy nhiên, đặc tả KEY nhƣ đã mô tả ở đây (cho dù nó là đúng về mặt logic) là cũng không thích đáng, với nghĩa là nó không chặn đƣợc biến quan hệ S_DURING chứa (ví dụ) cả hai bộ giá trị sau:
S2 CMC 10 SaiGon [d07, d10] S2 CMC 10 SaiGon [d02, d08]
Nhƣ bạn đọc thấy, hai bộ giá trị này hiển thị những dƣ thừa nào đó, bởi vì thông tin liên quan đến nhà cung cấp S2 vào ngày 7 và 8 đƣợc ghi lại đến 2 lần.
Đặc tả khoá là cũng không thích đáng theo chừng mực khác. Cụ thể là, nó không chặn đƣợc biến quan hệ S_DURING chứa cả hai bộ giá trị sau:
S2 CMC 10 SaiGon [d02, d06] S2 CMC 10 SaiGon [d07, d10]
Ở đây không có sự dƣ thừa, nhƣng lại có những “vòng vo” nhất định, vì ta đang nói đến 2 bộ mà có thể sẽ tốt hơn khi gộp làm một:
S2 CMC 10 SaiGon [d02, d10]
Rõ ràng là, để tránh đƣợc những dƣ thừa và vòng vo đó, ta cần có một ràng buộc -- giả sử gọi là ràng buộc C1 – nhƣ sau:
“ Nếu hai bộ phân biệt của S_DURING là giống hệt nhau trừ giá trị DURING
iB1B và iB2B của chúng, thì iB1BMERGES iB2B phải là sai”.
(Nhắc lại rằng MERGES là OR (hoặc) của OVERLAPS và MEETS, nói một cách thông thƣờng; thay thế MERGES bởi OVERLAPS trong ràng buộc C1 cho ta ràng buộc cần thiết để tránh đƣợc sự dƣ thừa; thay thế nó bởi MEETS cho ta ràng buộc cần thiết để tránh đƣợc sự vòng vo.). Cũng cần phải làm rõ rằng: có một cách đơn giản để bắt rằng buộc C1 tuân theo: đó là bằng cách giữ cho biến quan hệ
S_DURING đƣợc hợp nhất tại mọi thời điểm trong thuộc tính DURING. Do đó ta định nghĩa một mệnh đề HỢP NHẤT– COALESCED mà nó có thể tuỳ ý xuất hiện trong một định nghĩa biến quan hệ nhƣ sau:
VAR S_DURING BASE RELATION
{S# S#, TENCONGTY CHAR, TRANGTHAI INTEGER, DIACHI CHAR, DURING INTERVAL (DATE)}
KEY {S#, DURING} COALESCED DURING; /* Vẫn chƣa thích đáng! */
Đặc tả COALESCED DURING ở đây nghĩa là biến quan hệ S_DURING đó phải đồng nhất tại mọi thời điểm với kết quả của biểu thức S_DURING COALESCE DURING (hàm ý là việc hợp nhất S_DURING trên DURING do đó không có ảnh
hƣỏng gì). Bởi vậy cú pháp đặc biệt này đủ để giải quyết vấn đề về dƣ thừa và vòng vo. Chú ý: Ta giả sử từ lúc này bất kỳ cố gắng nào để cập nhật S_DURING theo cách để nó không ở dạng hợp nhất toàn phần trên DURING sẽ đơn giản bị loại bỏ. Tuy nhiên, hãy xem thêm thảo luận về vấn đề này trong Phần 1.4.6 (Toán tử Update trên khoảng).
Đáng tiếc là những đặc tả về KEY và COALESCED vẫn khá không hoàn toàn thích đáng vì, không chặn đƣợc biến quan hệ S_DURING chứa (ví dụ) cả 2 bộ sau:
S2 CMC 10 SaiGon [d02, d08] S2 CMC 20 SaiGon [d07, d10]
Ở đây nhà cung cấp S2 đƣợc chỉ ra có trạng thái cả hai giá trị 10 và 20 vào ngày d07 và d08 – đó là một trạng thái không thể có. Hay nói cách khác, ta đang có một sự mâu thuẫn ở đây.
Rõ ràng là, để tránh đƣợc những mâu thuẫn đó ta phải có một ràng buộc trên biến quan hệ - ta gọi đó là ràng buộc C2 – nhƣ sau:
“ Nếu hai bộ của S_DURING phân biệt có giá trị DURING i1B B và iB2B sao cho iB1
BOVERLAPS iB2B là đúng, khi đó các bộ này phải là đồng nhất loại trừ cho giá trị DURING của chúng”.
Chú ý cẩn thận rằng ràng buộc C2 là không bị bắt buộc phải đƣợc tuân thủ bằng cách giữ S_DURING hợp nhất trên DURING (và hiển nhiên là nó không bị bắt buộc bởi sự kiện {S#, DURING} là một khoá dự tuyển). Nhƣng giả sử là biến quan hệ
S_DURING là đƣợc giữ ở dạng trải mở tại mọi thời điểm trên thuộc tính DURING. Khi đó:
Khóa ứng cử duy nhất cho dạng hợp nhất S_DURING UNFOLD DURING
trƣớc nào, bất kỳ nhà cung cấp cho trƣớc nào đƣợc ký hợp đồng cũng chỉ có một tên, một trạng thái và một địa chỉ)
Do đó không có hai bộ có thể cùng có giá trị S# giống nhau và các giá trị
DURING gối nhau (bởi vì mọi giá trị DURING là các khoảng đơn vị trong
S_DURING UNFOLD DURING, và hai bộ có cùng giá trị S# và giá trị
DURING gối nhau là các bộ đôi của nhau –thực tế, chúng có thể là cùng một bộ).
Suy ra là nếu ta áp đặt ràng buộc {S#, DURING} là một khóa ứng cử cho
S_DURING UNFOLD DURING, thì ràng buộc C2 phải là “tự động”. Do đó ta định nghĩa một mệnh đề I_KEY mới (I_ là viết tắt của Interval) mà có thể tùy ý xuất hiện tại vị trí của mệnh đề KEY thông thƣờng nhƣ sau:
VAR S_DURING BASE RELATION
{S# S#, TENCONGTY CHAR, TRANGTHAI INTEGER, DIACHI CHAR, DURING INTERVAL (DATE)}
I_KEY {S#, DURING UNFOLDED} COALESCED DURING;
(mang ý nghĩa chính xác nhƣ sau: {S#, DURING} là một khóa ứng cử cho
S_DURING UNFOLD DURING). Đặc tả I_KEY này đủ để giải quyết vấn đề mâu thuẫn.
UChú ý rằng:U nếu {S#, DURING} là một khóa ứng cử cho S_DURING UNFOLD DURING thì hiển nhiên là khóa ứng cử cho S_DURING; sự kiện đó cho phép chúng ta loại bỏ đặc tả KEY gốc cho S_DURING thay vì đã đƣợc đặc tả bởi I_KEY. {S#,
DURING} về mặt ý nghĩa có thể đƣợc xem là một khóa ứng cử thời gian theo nghĩa ở Phần 1.3.3 (Các vấn đề về thời gian hoá). Hơn nữa, nhƣ ta vừa nhận thấy khóa ứng cử thời gian này thực sự là khóa ứng cử đúng đối với biến quan hệ chứa nó (không giống nhƣ các khóa thời gian đã trình bày trong Phần 1.3.3).
Tất nhiên, nếu cú pháp I_KEY đó đƣợc hỗ trợ cho các khóa ứng cử, ta có thể mong đợi nó cũng có khả năng hỗ trợ cho các khóa ngoài. Do đó, định nghĩa về
SP_DURING có thể bao hàm nhƣ sau:
FOREIGN I_KEY {S#, DURING UNFOLDED} REFERENCES S_DURING...
Mục tiêu ở đây là, nếu SP_DURING chỉ ra nhà cung cấp Sx là có thể cung cấp mặt hàng nào nào đó trong khoảng i, thì S_DURING phải chỉ ra rằng nhà cung cấp Sx
đó là đƣợc ký hợp đồng suốt toàn bộ khoảng i. Nếu ràng buộc này đƣợc thỏa mãn, thì tổ hợp thuộc tính {S#, DURING} về mặt ý nghĩa có thể đƣợc xem là một khoá ngoài thời gian theo nghĩa ở Phần 1.3.3. (Tuy nhiên nó vẫn không phải là một khóa ngoài đúng trong ngữ cảnh truyền thống).
Ta phải làm rõ một vấn đề nữa về biến quan hệ S_DURING. Giả sử, thực tế ta đặt biến quan hệ đó hợp nhất trong DURING tại mọi thời điểm. Cũng giả sử rằng thỉnh thoảng ta thực hiện một thủ tục để tính toán lại tình trạng của các nhà cung cấp đã đƣợc ký hợp đồng. Tất nhiên là thủ tục đó ghi lại cẩn thận giá trị trạng thái trƣớc đó trong S_DURING. Hiện tại, đôi khi sự tính toán cho kết quả là không thay đổi trạng thái. Trong trƣờng hợp đó, nếu thủ tục cố gắng một cách mò mẫm để thêm vào một bản ghi của trạng thái trƣớc đó trong S_DURING, nó sẽ vi phạm đặc tả
COALESCED. Để tránh đƣợc những vi phạm đó, thủ tục này sẽ phải thực hiện một kiểm tra đặc biệt cho “không thay đổi trạng thái” và thực hiện một UPDATE thích hợp thay vì INSERT để thực hiện công việc khi trạng thái thay đổi. Tất nhiên, có một khả năng khác ta có thể lựa chọn không giữ hợp nhập S_DURING trong
DURING – một giải pháp có thể không thích hợp trong trƣờng hợp đặc biệt này, nhƣng có thể tích hợp trong một số trƣờng hợp khác.
1.4.6- Toán tử Update trên khoảng: