Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> SQL

Mối quan hệ Unary One-to-Many (Một-nhiều đệ quy) trong DBMS


Unary Relationship (Mối quan hệ đệ quy / tự tham chiếu) là mối quan hệ giữa các instance (thể hiện) của **chính một entity type (loại thực thể)**. One-to-Many Unary** nghĩa là một instance đóng vai "cha" (parent) liên kết với nhiều instance đóng vai "con" (child), nhưng tất cả đều thuộc cùng một bảng.

Ví dụ kinh điển: Employee - Manager

Bảng Employee:

Emp_ID (PK) Emp_Name Manager_ID (FK)
1CEONULL
2CTO1
3Dev Lead2
4Dev A3
5Dev B3
  • Manager_ID là **Foreign Key** tự tham chiếu về Emp_ID của cùng bảng.
  • Một Manager (Emp_ID=2) quản lý nhiều Employee (Emp_ID=3,4,5...).
  • CEO (Emp_ID=1) không có Manager -> Manager_ID = NULL.

Hai vai trò (Role Groups) trong quan hệ

Vai tròMô tảVí dụ
Manager (Parent/Supervisor)Instance đóng vai "quản lý", "cha"CEO, CTO, Dev Lead
Employee (Subordinate/Child)Instance đóng vai "cấp dưới", "con"Tất cả nhân viên (kể cả Manager cũng là Employee của người khác)

Đặc thù tham gia (Participation Constraints)

1. Optional - Mandatory (Thường gặp nhất)

  • Manager role: Optional. Không phải Employee nào cũng là Manager (CEO không quản lý ai? CEO quản lý CTO. Nhưng Dev A, Dev B không quản lý ai). Có instance không tham gia vai Manager.
  • Employee role: Mandatory. Mọi instance **phải** là Employee (của ai đó), **TRỪ** instance gốc (Root/CEO). → **Vi phạm** mandatory participation tại root.

Giải pháp: Cho phép Manager_ID NULL cho root. Khi đó Employee role thực tế là **Optional** cho root, Mandatory cho các instance khác. Mô hình thường là Optional-Optional hoặc Optional-Mandatory với ngoại lệ root.

2. Optional - Optional

  • Cả hai vai trò đều Optional.
  • Instance có thể không là Manager (không có cấp dưới).
  • Instance có thể không có Manager (root/CEO).
  • Hợp lý nhất cho cấu trúc tổ chức thực tế.

3. Mandatory - Mandatory (Hiếm, chỉ lý thuyết)

  • Mọi instance PHẢI vừa là Manager (có ít nhất 1 cấp dưới) VỪA là Employee (có Manager).
  • → Vô tận hoặc vòng tròn (cycle). Không thực tế cho org chart.

ER Diagram (Sơ đồ ER) ký hiệu

Employee (Entity)
   |
   | 1 (Manager)          M (Employee)
   |----------------------|
   |  Manages / Reports_to |
   |______________________|
   (Recursive relationship)

Triển khai SQL

CREATE TABLE Employee (
  Emp_ID INT PRIMARY KEY,
  Emp_Name VARCHAR(100) NOT NULL,
  Manager_ID INT,
  FOREIGN KEY (Manager_ID) REFERENCES Employee(Emp_ID)
    ON DELETE SET NULL   -- Xóa manager -> cấp dưới thành NULL (hoặc CASCADE nếu quy định)
    ON UPDATE CASCADE
);

-- Index cho FK để join nhanh
CREATE INDEX idx_emp_manager ON Employee(Manager_ID);

Truy vấn đệ quy (Recursive Query) - CTE

Lấy toàn bộ cấp dưới của một Manager (PostgreSQL, SQL Server, Oracle, MySQL 8+):

WITH RECURSIVE Subordinates AS (
  -- Anchor: Manager trực tiếp
  SELECT Emp_ID, Emp_Name, Manager_ID, 1 AS Level
  FROM Employee
  WHERE Manager_ID = 2  -- CTO

  UNION ALL

  -- Recursive: Cấp dưới của cấp dưới
  SELECT e.Emp_ID, e.Emp_Name, e.Manager_ID, s.Level + 1
  FROM Employee e
  INNER JOIN Subordinates s ON e.Manager_ID = s.Emp_ID
)
SELECT * FROM Subordinates;

Các ví dụ Unary One-to-Many khác

  • Category/Menu đệ quy: Danh mục cha/con (CategoryID, ParentCategoryID).
  • Bill of Materials (BOM): Thành phần cha/con sản xuất (PartID, ParentPartID).
  • File System: Thư mục/Folder (FolderID, ParentFolderID).
  • Comment/Reply: Bình luận cha/con (CommentID, ParentCommentID).

Lưu ý thiết kế

  • Luôn index FK (Manager_ID) để truy vấn con nhanh.
  • Tránh chu trình (cycle): A quản lý B, B quản lý A. Dùng trigger hoặc application logic kiểm tra.
  • Cân nhắc path enumeration (materialized path: 1/2/3/4) hoặc nested set cho read-heavy hierarchy.
  • Phân biệt rõ Role Name: "Manages" vs "Reports To" để không nhầm lẫn direction.