Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Cách tạo nhiều cái cho một cái

Bạn đang sử dụng kế thừa (còn được gọi là trong mô hình mối quan hệ thực thể là "lớp con" hoặc "danh mục"). Nói chung, có 3 cách để biểu diễn nó trong cơ sở dữ liệu:

  1. "Tất cả các lớp trong một bảng": Chỉ có một bảng "bao gồm" tất cả các lớp cha và con (nghĩa là với tất cả các cột cha và con), với ràng buộc CHECK để đảm bảo tập hợp con phù hợp của các trường không phải là NULL (tức là hai phần con khác nhau không "trộn lẫn").
  2. "Lớp bê tông trên mỗi bảng": Có một bảng khác nhau cho mỗi đứa trẻ, nhưng không có bảng cha. Điều này yêu cầu các mối quan hệ của cha mẹ (trong trường hợp của bạn là Khoảng không quảng cáo <- Bộ nhớ) phải được lặp lại ở tất cả các phần tử con.
  3. "Lớp trên mỗi bàn": Có một bảng phụ huynh và một bảng riêng cho mỗi đứa trẻ, đó là điều bạn đang cố gắng thực hiện. Điều này là rõ ràng nhất nhưng có thể làm tốn kém 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ừ phần con và bỏ qua phần chính).

Tôi thường thích cách tiếp cận thứ 3 hơn, nhưng thực thi cả sự hiện diện tính độc quyền của một đứa trẻ ở cấp độ ứng dụng. Việc thực thi cả hai ở cấp cơ sở dữ liệu là một chút rườm rà, nhưng có thể thực hiện được nếu DBMS hỗ trợ các ràng buộc hoãn lại. Ví dụ:

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)
    )
)

Điều này sẽ thực thi cả tính độc quyền (do CHECK ) và sự hiện diện (do sự kết hợp của CHECKFK1 / FK2 ) của đứa trẻ.

Thật không may, MS SQL Server không hỗ trợ các ràng buộc hoãn lại, nhưng bạn có thể "ẩn" toàn bộ hoạt động đằng sau các thủ tục được lưu trữ và cấm máy khách trực tiếp sửa đổi bảng.

Chỉ có thể thực thi tính độc quyền mà không có các ràng buộc hoãn lại:

STORAGE_TYPE là một bộ phân biệt kiểu, thường là một số nguyên để tiết kiệm dung lượng (trong ví dụ trên, 0 và 1 được ứng dụng của bạn "biết" và được diễn giải theo đó).

VAN.STORAGE_TYPEWAREHOUSE.STORAGE_TYPE có thể được tính toán (hay còn gọi là. "tính") để tiết kiệm dung lượng lưu trữ và tránh yêu cầu CHECK s.

--- CHỈNH SỬA ---

Các cột được tính toán sẽ hoạt động trong SQL Server như sau:

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 yêu cầu cột được tính toán được sử dụng ở nước ngoài key để được PERSISTED. 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), điều này có thể tiết kiệm một số không gian lưu trữ.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Máy chủ SQL CHỌN VÀO @variable?

  2. Cách xử lý lỗi trong giao dịch lồng nhau của máy chủ SQL

  3. Cách trả lại tất cả các ràng buộc kiểm tra không đáng tin cậy trong SQL Server (Ví dụ T-SQL)

  4. SQL Server:Truy vấn nhanh, nhưng chậm so với thủ tục

  5. Khi nào tôi nên sử dụng ĐĂNG KÝ CHÉO qua THAM GIA INNER?