Unary One-to-One Relationship (Mối quan hệ một-một đệ quy) là mối quan hệ giữa các instance của **chính một entity type**, nơi mỗi instance tối đa liên kết với **một** instance khác của cùng entity, và ngược lại. Hai instance đóng **cùng một vai trò (role group)**.
Ví dụ kinh điển: Người kết hôn (Marriage)
Bảng Person:
| Person_ID (PK) | Person_Name | Spouse_ID (FK) |
|---|---|---|
| 1 | An | 2 |
| 2 | Bình | 1 |
| 3 | Cường | NULL |
- An (1) kết hôn với Bình (2) ->
Spouse_IDtrỏ lẫn nhau. - Cường (3) độc thân ->
Spouse_ID = NULL. - Mối quan hệ MARRIED_TO là đối xứng (symmetric).
Ba trường hợp Participation Constraints (Ràng buộc tham gia)
1. Mandatory - Mandatory (Bắt buộc - Bắt buộc)
- Mọi Person **phải** có Spouse (Spouse_ID NOT NULL).
- Mọi Person **phải** là Spouse của một Person khác.
- → Mọi người đều đã kết hôn, không ai độc thân. Khó thực thi (insert chicken-egg).
- Thường chỉ dùng trong lý thuyết hoặc hệ thống closed (ví dụ: cặp đôi đồ vật luôn thành đôi).
2. Optional - Optional (Tùy chọn - Tùy chọn) - Phổ biến nhất
- Person **có thể** có Spouse (kết hôn) hoặc không (độc thân).
- Person **có thể** là Spouse của ai đó hoặc không.
Spouse_IDcho phép NULL.- Ví dụ mở rộng: Nộp thuế riêng lẻ hoặc chung. Cặp đôi có tùy chọn nộp chung (Joint) hoặc riêng (Separate). Ít nhất một cặp chọn riêng.
3. Optional - Mandatory (hoặc Mandatory - Optional)
- Một vai trò bắt buộc tham gia, vai kia tùy chọn.
- Ví dụ: Mỗi người **phải** có một "Người đại diện pháp lý" (Legal Guardian), nhưng Người đại diện **có thể** đại diện cho nhiều người (thì thành One-to-Many). One-to-One Mandatory-Optional hiếm gặp thực tế.
ER Diagram
Person (Entity) | | 1 (Spouse) 1 (Spouse) |----------------------| | MARRIED_TO | |______________________| (Recursive, Symmetric)
Triển khai SQL - Đảm bảo đối xứng (Symmetric)
Vấn đề: Insert An (Spouse=2) và Bình (Spouse=1) cần transaction. Cần trigger/check constraint đảm bảo đối xứng.
CREATE TABLE Person (
Person_ID INT PRIMARY KEY,
Person_Name VARCHAR(100) NOT NULL,
Spouse_ID INT UNIQUE, -- UNIQUE đảm bảo One-to-One (mỗi người chỉ là spouse của 1 người)
FOREIGN KEY (Spouse_ID) REFERENCES Person(Person_ID)
ON DELETE SET NULL -- Vợ/chồng chết -> người kia độc thân
ON UPDATE CASCADE
);
-- Trigger đảm bảo đối xứng (PostgreSQL example)
CREATE OR REPLACE FUNCTION enforce_symmetric_spouse()
RETURNS TRIGGER AS $$
BEGIN
IF NEW.Spouse_ID IS NOT NULL THEN
-- Cập nhật spouse của người kia trỏ về mình
UPDATE Person SET Spouse_ID = NEW.Person_ID WHERE Person_ID = NEW.Spouse_ID;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_symmetric_spouse
AFTER INSERT OR UPDATE OF Spouse_ID ON Person
FOR EACH ROW EXECUTE FUNCTION enforce_symmetric_spouse();
So sánh One-to-One Unary vs Binary
| Đặc điểm | Unary One-to-One (Đệ quy) | Binary One-to-One (2 bảng) |
|---|---|---|
| Số bảng | 1 bảng | 2 bảng |
| FK | Tự tham chiếu (Self-referencing) | Bảng con tham chiếu bảng cha |
| Vai trò | Cùng một vai trò (Spouse - Spouse) | Hai vai trò khác (Person - Passport) |
| Ví dụ | Kết hôn, Đôi bạn thân, Buddy system | Person - Passport, User - Profile |
| Đối xứng | Thường đối xứng | Không đối xứng |
Ví dụ khác: Buddy System (Hệ thống bạn đồng hành)
- Mỗi nhân viên mới được gán 1 "Buddy" (nhân viên cũ) hướng dẫn.
- Buddy cũng là Employee.
- Quan hệ: Employee (Newbie) - Buddy (Mentor). Có thể coi là Unary One-to-One (nếu 1-1) hoặc One-to-Many (1 Buddy hướng dẫn nhiều Newbie).
Best Practices
- Dùng
UNIQUEconstraint trên FK (Spouse_ID) để enforce One-to-One. - Cho phép
NULLcho Optional participation. - Dùng Trigger / Application Logic để duy trì đối xứng (nếu cần).
- Cân nhắc tách bảng nếu logic phức tạp:
Marriagetable (Person_ID1, Person_ID2, Start_Date, End_Date) - linh hoạt hơn, hỗ trợ ly hôn, tái hôn, history.