Thiết kế hiện tại của bạn được gọi là vòng cung độc quyền trong đó bảng sets
có hai khóa ngoài và cần chính xác một trong số đó là không rỗng. Đây là một cách để thực hiện các mối liên kết đa hình, vì một khoá ngoại đã cho chỉ có thể tham khảo một bảng đích.
Một giải pháp khác là tạo một "siêu phổ biến" chung mà cả hai tham chiếu users
và schools
, sau đó sử dụng làm phụ huynh của sets
.
create table set_owner
create table users
PK is also FK --> set_owner
create table schools
PK is also FK --> set_owner
create table sets
FK --> set_owner
Bạn có thể nghĩ về điều này như tương tự với một giao diện trong mô hình OO:
interface SetOwner { ... }
class User implements SetOwner { ... }
class School implements SetOwner { ... }
class Set {
SetOwner owner;
}
Re bình luận của bạn:
Vì vậy, các bảng SetOwner chứa cả userIds và SchoolID, đúng không? Điều đó có nghĩa là tôi sẽ không được phép có cùng một ID cho người dùng và trường học. Làm thế nào tôi có thể thực thi điều này?
Để bảng SetOwners tạo giá trị id. Bạn phải chèn vào SetOwners trước khi bạn có thể chèn vào Người dùng hoặc Trường học. Vì vậy, hãy tạo id trong Số người dùng và trường học không tự động tăng thêm; chỉ sử dụng giá trị được tạo bởi SetOwners:
INSERT INTO SetOwners DEFAULT VALUES; -- generates an id
INSERT INTO Schools (id, name, location) VALUES (LAST_INSERT_ID(), 'name', 'location');
Bằng cách này, giá trị id đã cho sẽ không được sử dụng cho cả trường học và người dùng.
Nếu tôi muốn nhận loại chủ sở hữu cho tập hợp, tôi có cần thuộc tính ownerType trong bảng SetOwner của tôi không?
Bạn chắc chắn có thể làm điều này. Trong thực tế, có thể có các cột khác chung cho cả Người dùng và Trường học, và bạn có thể đặt các cột này trong SetOwners siêu cấp. Điều này được đưa vào mẫu Class Table Inheritance của Martin Fowler.
Và nếu tôi muốn lấy tên trường hoặc người dùng (tùy theo loại nào), tôi có thể thực hiện điều này bằng một truy vấn hay không? để có được tên)?
Bạn cần tham gia. Nếu bạn đang truy vấn từ một Tập hợp nhất định và bạn biết nó thuộc về một người dùng (không phải trường học), bạn có thể bỏ qua việc tham gia vào SetOwners và tham gia trực tiếp với Người dùng. Tham gia không nhất thiết phải đi bằng các khóa ngoại.
SELECT u.name FROM Sets s JOIN Users u ON s.SetOwner_id = u.id WHERE ...
Nếu bạn không biết liệu một tập hợp thuộc về một tài khoản hoặc một trường, bạn sẽ phải làm một bên ngoài tham gia vào cả hai:
SELECT COALESCE(u.name, sc.name) AS name
FROM Sets s
LEFT OUTER JOIN Users u ON s.SetOwner_id = u.id
LEFT OUTER JOIN Schools sc ON s.SetOwner_id = sc.id
WHERE ...
Bạn biết rằng SetOwner_id phải phù hợp với một hoặc bảng khác, Người dùng hoặc Trường học, nhưng không phải cả hai.
Bạn muốn sử dụng đồ họa nào? – basszero
@basszero: MySQL Workbench –
wow! Đó là một chặng đường dài kể từ lần cuối cùng tôi thử nó! – basszero