Quá trình mô hình hóa dữ liệu trải qua 3 giai đoạn chính, trong đó giai đoạn mô hình hóa khái niệm là quan trọng nhất để nắm bắt yêu cầu nghiệp vụ. Mô hình có hoạt động được chính xác hay không, có đáp ứng được yêu cầu của bài toán hay không là ở giai đoạn này. Với những bài toán đơn giản, ta thường bỏ qua bước này mà vào ngay giai đoạn mô hình hóa logic. Nhưng ta không thể làm như vậy với những yêu cầu phức tạp vì nó tiềm ẩn rủi ro cao.
Do đó, mô hình hóa khái niệm mang lại nhiều giá trị lớn. Trong quá trình đó, ta cần phải làm một việc rất quan trọng mà ảnh hưởng xuyên suốt tới các giai đoạn sau của dữ liệu, thậm chí tới cả ứng dụng tác nghiệp cũng như đi tới cả vùng khai thác như Data Warehouse và Big Data sau này: Xác định key hay identity của dữ liệu.
Ở giai đoạn mô hình hóa khái niệm, key không nên là những giá trị tự tăng - auto increment (trừ một vài trường hợp đặc biệt nơi mà dữ liệu được sinh ra khởi nguồn từ bài toán của ta) mà nên được xác định bằng chính những thuộc tính làm nên dữ liệu đó. Key bao gồm những loại khác nhau và đó là nội dung của bài viết này. Bài viết này cũng nhằm mục đích chuẩn bị cho phần chuẩn hóa 2NF - The Second Normal Form.
Phần này chúng ta sẽ bàn về:
- Concatenated key
- Superkey
- Candidate key
- Subkey
Superkey
Superkey là một tập hợp thuộc tính xác định tính duy nhất cho từng tuple trong một relation.
Nhớ lại định nghĩa về relational database (RD), mọi tuple (row) phải là duy nhất, nghĩa là không thể có hai tuple nào giống hệt nhau. Từ định nghĩa trên ta thấy superkey có thể là một thuộc tính hoặc một tập hợp thuộc tính miễn sao nó có thể xác định được duy nhất 1 tuple.
Một superkey có thể có các thuộc tính dư thừa; nghĩa là, nó có thể chứa nhiều hơn các thuộc tính cần thiết để xác định duy nhất một hàng. Bất kỳ tập thuộc tính nào có thể xác định duy nhất một hàng trong bảng đều là superkey. Cùng làm rõ qua ví dụ.
BatchId | InvoiceId | ProcessDate | PastDate |
97 | 322 | 2015-01-01 | 0 |
98 | 325 | 2015-01-02 | 0 |
98 | 341 | 2015-01-02 | 0 |
99 | 322 | 2015-01-03 | 1 |
99 | 350 | 2015-01-03 | 0 |
99 | 351 | 2015-01-03 | 0 |
100 | 351 | 2015-01-03 | 0 |
Cùng xác định superkey của bảng thông qua dữ liệu mẫu (ở đây, tôi nhấn mạnh dữ liệu mẫu vì ta đang dự đoán).
Yêu cầu cùa superkey hay key nói chung là từ 1 giá trị của key chỉ xác định được đúng một giá trị của các thuộc tính khác trong cùng một dòng với nó.
Xem xét BatchId, ta thấy thuộc tính này không thể làm key được vì với cùng BatchId = 98 ta xác định được hai giá trị InvoiceId = {325, 341}.
Tương tự, InvoiceId cũng không thể vì khi InvoiceId = 351, ta xác định được BatchId = {99, 100}.
ProcessDate và PastDate cũng vậy.
Vậy ta cần nghĩ tới một tập hợp thuộc tính.
Đầu tiên, RD cần đảm bảo tính duy nhất của mỗi dòng thì superkey luôn có là chính bản thân cả dòng đó: superkey1 = { BatchId, InvoiceId, ProcessDate, PastDate }
.
Để xác định các superkey tiếp theo, ta thử bỏ ra khỏi superkey1 vừa tìm được các thuộc tính hoặc các tập hợp thuộc tính con của nó.
- Bỏ { PastDate }, ta có
superkey2 = { BatchId, InvoiceId, ProcessId }
. Superkey2 thỏa mãn vì 3 thuộc tính của nó là duy nhất cho mỗi dòng. - Bỏ { ProcessDate }, ta có
superkey3 = { BatchId, InvoiceId, PastDate }
thỏa mãn. - Bỏ { ProcessDate, PastDate }, ta có
superkey4 = { BatchId, InvoiceId }
thỏa mãn. - Liệu có bỏ được thêm nữa không? Nếu bỏ { InvoiceId } hoặc { BatchId }, thuộc tính còn lại không đảm bảo được tính duy nhất. Do đó, không thỏa mãn.
Ở mục sau, bạn sẽ thấy trong 4 superkey vừa tìm được sẽ có những cái trở thành candidate key.
Concatenate key
Concatenated Key, hay còn gọi là Compound Key/Composite Key, là dạng key trong đó bao gồm nhiều thuộc tính.
Concatenated key xuất hiện khi một thuộc tính đơn lẻ không đủ để xác định tính duy nhất của bản ghi. Các trường hợp concatenated key phổ biến:
- Mối quan hệ many-to-many
- Các thực thể phức hợp (composite entities)
- Các cấu trúc phân cấp (hierarchical structures)
- Cấu trúc dữ liệu đa chiều (multidimensional data)
Ví dụ, Ta có hai thực thể Student và Course. Trong đó, mỗi student có thể đăng ký học nhiều course và mỗi course lại có thể được đăng ký bởi nhiều student. Đây là mối quan hệ many-to-many. Ta có bảng thể hiện mối quan hệ đó như sau: Student nào đang học môn nào và có điểm bao nhiêu.
StudentID | CourseID | Grade |
1 | Math | A |
1 | Science | B |
2 | Math | C |
2 | English | A |
Candidate key
Candidate key còn được gọi là key, là một superkey tối giản.
Chặt chẽ hơn:
Gọi K là một tập các thuộc tính của relation R.
K là một candidate key của R khi và chỉ khi cả hai tính chất sau thỏa mãn:
1. Tính duy nhất: không có hai tuple phân biệt nào chứa cùng giá trị của K.
2. Tính tối giản: không có tập con nào của K mang tính duy nhất.
Tính duy nhất giúp xác định superkey.
Tính tối giản giúp xác định candidate key.
Ở ví dụ bảng 1 trên, trong 4 superkey đã xác định thì có superkey4 = { BatchId, InvoiceId } là candidate key vì
- Nó là một superkey, và
- Nó không thể tối giản hơn nữa, nghĩa là ta không thể bỏ bất kỳ thuộc tính nào trong đó để vẫn đảm bảo xác định được duy nhất 1 bản ghi.
Có nhiều candidate key
Mỗi relation có thể có nhiều candidate key. Ví dụ:
EmployeeID | PhoneNumber | NationalID | Name | |
001 | alice@example.com | 0912345678 | 1001 | Alice |
002 | bob@example.com | 0918765432 | 1004 | Bob |
003 | charlie@example.com | 0911122233 | 1002 | Charlie |
Trong bảng 3, ta thấy có 3 candidate key là
- Candidate key 1 = { EmployeeID }
- Candidate key 2 = { Email }
- Candidate key 3 = { PhoneNumber }
Sau này, ta sẽ phải lựa chọn primary key từ 1 trong số các candidate key này.
Một số vấn đề cần bàn:
- Thế nào là một key có giá trị NULL?
- Candidate key có thể NULL không và tại sao? trong tình huống nào nó có thể chứa NULL?
1. Thế nào là một key NULL?
Key bị coi là NULL khi một hoặc nhiều thuộc tính cấu thành nó bị NULL.
NULL không được coi là một giá trị, nó là "không xác định", do đó, nó không thể so sánh hay dùng làm định danh.
2. Candidate key có thể NULL không?
Có thể, tuy nhiên ta nên hạn chế.
Nếu một candidate key có thể chứa NULL thì nó có thể dẫn đến các vấn đề về tính duy nhất và tính toàn vẹn của dữ liệu vì lý do chính là ta không thể so sánh hai giá trị NULL với nhau.
Giả sử với relation Employee (EmployeeID, Name, Age) -> ký hiệu gạch chân cho thấy thuộc tính là key. Giả sử, EmployeeID có NULL. Khi đó, từ key ta không thể phân biệt được hai dòng sau:
(NULL, Nguyễn Văn A, 20) và
(NULL, Nguyễn Hữu B, 21).
"Quy trình" xác định key
Sở dĩ có những key có NULL là vì khi modeling bài toán, thường thì người thiết kế sẽ có một chút dữ liệu mẫu trong tay (thông qua dữ liệu mẫu, file, hỏi yêu cầu người dùng,...) và dữ liệu này, ví dụ với Employee trên, ở thuộc tính EmployeeID người thiết kế chia được thành hai nhóm:
- Nhóm 1: Bao gồm 300 bản ghi có EmployeeID khác NULL và hoàn toàn unique.
- Nhóm 2: Bao gồm 100 bản ghi có EmployeeID NULL vì có thể do chất lượng dữ liệu ở hệ thống nguồn có vấn đề.
Như vậy, tình huống này EmployeeID có thể được xác định là candidate key. Tuy nhiên, nó sẽ không được đưa vào làm primary key vì primary key yêu cầu khác NULL chặt chẽ.
Khi gặp vấn đề này, ta chia thành hai tình huống:
- Tình huống 1: Nếu relation này còn có thêm ít nhất một candidate key khac NULL khác. Như vậy ta có thể lựa chọn một trong những candidate key đó làm primary key.
- Tình huống 2: Relation này chỉ có duy nhất EmployeeID (NULLABLE) này là candidate key.
Tính huống 2 khó giải quyết hơn. Ta không nên tặc lưỡi tạo một primary key tự tăng được vì như vậy, chỉ giải quyết được vấn đề bề ngoài mà về mặt bản chất dữ liệu là đang sai.
- Tìm kiếm trong relation có thông tin khác unique mà ta bỏ qua không.
- Cùng nghiệp vụ phân tích xem còn thông tin nào khác mà ta đã bỏ quên chưa đưa vào mô hình không.
- Nếu trường hợp nghiệp vụ là tạo ra những bản ghi mới hoàn toàn, tức là dữ liệu mà ta đang mô hình hóa là nơi đầu tiên nó xuất hiện xuyên suốt hệ thống trong tổ chức của ta, ta có thể sử dụng các khóa dạng đại diện như Auto Increment, Snowflake, UUID. Ví dụ: Hệ thống tạo căn cước công dân.
Một thông tin bổ sung nữa về candidate key và primary key: Trong khi candidate key được xác định ở giai đoạn mô hình hóa nghiệp vụ (conceptual model, logical model) thì primary key được xác định ở giai đoạn triên khai cụ thể hơn (logical model, physical model).
Subkey
Subkey là một tập hợp con của một candidate key.
Vì là tập con của một candidate key (là key đã tối giản) nên subkey không đảm bảo tính duy nhất: Nếu lấy một tập hợp con từ một candidate key, tập hợp con này (tức là subkey) sẽ không đủ để xác định duy nhất mỗi bản ghi trong bảng.
Ví dụ, bảng 1 bên trên có candidate key là { BatchId, InvoiceId }. Ta có 3 tập con:
- { BatchID } là subkey
- { InvoiceID } là subkey
- { } không phải là subkey