Một cách khác (không có Null và không có chu kỳ trong các FOREIGN KEY
mối quan hệ) là có một bảng thứ ba để lưu trữ "những đứa trẻ yêu thích". Trong hầu hết các DBMS, bạn sẽ cần một UNIQUE
ràng buộc bổ sung TableB
.
@Aaron đã nhanh hơn để xác định rằng quy ước đặt tên ở trên khá cồng kềnh và có thể dẫn đến lỗi. Nó thường tốt hơn (và sẽ giữ cho bạn lành mạnh) nếu bạn không có Id
các cột trên tất cả các bảng của mình và nếu các cột (được nối) có cùng tên trong nhiều bảng xuất hiện. Vì vậy, đây là một đổi tên:
Parent
ParentID INT NOT NULL PRIMARY KEY
Child
ChildID INT NOT NULL PRIMARY KEY
ParentID INT NOT NULL FOREIGN KEY REFERENCES Parent (ParentID)
UNIQUE (ParentID, ChildID)
FavoriteChild
ParentID INT NOT NULL PRIMARY KEY
ChildID INT NOT NULL
FOREIGN KEY (ParentID, ChildID)
REFERENCES Child (ParentID, ChildID)
Trong SQL-Server (mà bạn đang sử dụng), bạn cũng có tùy chọn IsFavorite
cột bit mà bạn đề cập. Đứa trẻ yêu thích duy nhất của mỗi phụ huynh có thể được thực hiện thông qua Chỉ mục duy nhất được lọc:
Parent
ParentID INT NOT NULL PRIMARY KEY
Child
ChildID INT NOT NULL PRIMARY KEY
ParentID INT NOT NULL FOREIGN KEY REFERENCES Parent (ParentID)
IsFavorite BIT NOT NULL
CREATE UNIQUE INDEX is_FavoriteChild
ON Child (ParentID)
WHERE IsFavorite = 1 ;
Và lý do chính mà tùy chọn 1 của bạn không được khuyến nghị, ít nhất là không có trong SQL-Server, là do mô hình của các đường dẫn tròn trong các tham chiếu khóa ngoài có một số vấn đề.
Đọc một bài viết khá cũ: SQL theo thiết kế: Tham chiếu thông tư
Khi chèn hoặc xóa các hàng từ hai bảng, bạn sẽ gặp phải vấn đề "gà và trứng". Tôi nên chèn bảng nào trước - không vi phạm bất kỳ ràng buộc nào?
Để giải quyết điều đó, bạn phải xác định ít nhất một cột nullable. (OK, về mặt kỹ thuật bạn không cần phải có, bạn có thể có tất cả các cột như NOT NULL
nhưng chỉ trong DBMS, như Postgres và Oracle, đã triển khai các ràng buộc có thể bảo vệ được. Xem câu trả lời của @ Erwin trong một câu hỏi tương tự: Ràng buộc khóa ngoài phức tạp trong SQLAlchemy về cách điều này có thể được thực hiện trong Postgres). Tuy nhiên, thiết lập này cho cảm giác như trượt trên băng mỏng.
Kiểm tra một câu hỏi gần như giống hệt nhau tại SO (nhưng đối với MySQL) Trong SQL, hai bảng có liên quan đến nhau không? trong đó câu trả lời của tôi là khá nhiều như nhau. MySQL không có chỉ mục một phần nào, vì vậy các tùy chọn khả thi duy nhất là FK nullable và giải pháp bảng bổ sung.