Bạn đang sử dụng thừa kế (còn được gọi trong mô hình mối quan hệ thực thể là "phân lớp" hoặc "danh mục"). Nói chung, có 3 cách để biểu diễn nó trong cơ sở dữ liệu:
- "Tất cả các lớp trong một bảng": Có chỉ là một bảng "bao gồm" tất cả các lớp con phụ huynh và (tức là với tất cả cha mẹ và con cột), với ràng buộc CHECK để đảm bảo tập con đúng của trường là không NULL (tức là hai con khác nhau không "trộn").
- "Lớp bê tông trên mỗi bảng": Có bảng khác nhau cho từng trẻ, nhưng không có bảng cha. Điều này đòi hỏi mối quan hệ của cha mẹ (trong trường hợp của bạn Hàng tồn kho < - Lưu trữ) được lặp đi lặp lại ở tất cả trẻ em.
- "Lớp học trên mỗi bảng": Có bảng cha và bảng riêng cho từng trẻ em, đó là những gì bạn đang cố gắng làm. Điều này là sạch nhất, nhưng có thể tốn một số hiệu suất (chủ yếu là khi sửa đổi dữ liệu, không quá nhiều khi truy vấn vì bạn có thể tham gia trực tiếp từ con và bỏ qua phụ huynh).
Tôi thường thích cách tiếp cận thứ 3, nhưng thực thi cả hiện diện và độc quyền của một đứa trẻ ở cấp ứng dụng. Việc thực hiện cả hai ở cấp độ cơ sở dữ liệu là một chút cồng kềnh, nhưng có thể được thực hiện nếu DBMS hỗ trợ các ràng buộc hoãn lại. Ví dụ:
![enter image description here](https://i.stack.imgur.com/5O7FQ.png)
CHECK (
(
(VAN_ID IS NOT NULL AND VAN_ID = STORAGE_ID)
AND WAREHOUSE_ID IS NULL
)
OR (
VAN_ID IS NULL
AND (WAREHOUSE_ID IS NOT NULL AND WAREHOUSE_ID = STORAGE_ID)
)
)
này sẽ thực thi cả độc quyền (do CHECK
) và sự hiện diện (do sự kết hợp của CHECK
và FK1
/FK2
) của trẻ.
Thật không may, MS SQL Server does not support deferred constraints, nhưng bạn có thể "ẩn" toàn bộ hoạt động sau các thủ tục được lưu trữ và cấm khách hàng sửa đổi trực tiếp các bảng.
Chỉ cần độc quyền có thể được áp dụng mà không hạn chế chậm:
![enter image description here](https://i.stack.imgur.com/oOr2D.png)
Các STORAGE_TYPE
là một loại phân biệt, thường là một số nguyên để tiết kiệm không gian (trong ví dụ trên, 0 và 1 là " được biết đến "để ứng dụng của bạn và diễn giải cho phù hợp).
Các cột VAN.STORAGE_TYPE
và WAREHOUSE.STORAGE_TYPE
có thể được tính toán (còn gọi là "được tính toán") để lưu trữ và tránh sự cần thiết cho số CHECK
s.
--- EDIT ---
cột Điện Toán sẽ làm việc dưới SQL Server như thế này:
CREATE TABLE STORAGE (
STORAGE_ID int PRIMARY KEY,
STORAGE_TYPE tinyint NOT NULL,
UNIQUE (STORAGE_ID, STORAGE_TYPE)
);
CREATE TABLE VAN (
STORAGE_ID int PRIMARY KEY,
STORAGE_TYPE AS CAST(0 as tinyint) PERSISTED,
FOREIGN KEY (STORAGE_ID, STORAGE_TYPE) REFERENCES STORAGE(STORAGE_ID, STORAGE_TYPE)
);
CREATE TABLE WAREHOUSE (
STORAGE_ID int PRIMARY KEY,
STORAGE_TYPE AS CAST(1 as tinyint) PERSISTED,
FOREIGN KEY (STORAGE_ID, STORAGE_TYPE) REFERENCES STORAGE(STORAGE_ID, STORAGE_TYPE)
);
-- We can make a new van.
INSERT INTO STORAGE VALUES (100, 0);
INSERT INTO VAN VALUES (100);
-- But we cannot make it a warehouse too.
INSERT INTO WAREHOUSE VALUES (100);
-- Msg 547, Level 16, State 0, Line 24
-- The INSERT statement conflicted with the FOREIGN KEY constraint "FK__WAREHOUSE__695C9DA1". The conflict occurred in database "master", table "dbo.STORAGE".
Thật không may, SQL Server đòi hỏi cho một cột tính được sử dụng bằng ngoại khóa được CHẤP NHẬN. Các cơ sở dữ liệu khác có thể không có giới hạn này (ví dụ: các cột ảo của Oracle), có thể tiết kiệm một số không gian lưu trữ.
Hãy đánh giá kỹ nếu bạn thực sự cần mối quan hệ 1-1. Hầu hết thời gian khi bạn nghĩ rằng bạn cần một, bạn thực sự không. –
Sử dụng EER. Chìa khóa ở đây là để xác định loại mối quan hệ 'là a',' has'/'thuộc về', hoặc chúng là các kiểu con của cùng một siêu kiểu. Sau đó, giảm các thực thể của bạn xuống các bảng. – Oybek
Ahh ok, sau đó Bảng lưu trữ là một siêu lớp và Bảng Vạn/Kho là các kiểu con, nhưng bây giờ thì sao? lol – Luckyl337