Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Как да създадете множество едно към едно

Вие използвате наследяването (известно също в моделирането на същност-връзка като "подклас" или "категория"). Като цяло има 3 начина да го представите в базата данни:

  1. „Всички класове в една таблица“: Имайте само една таблица, "покриваща" родителските и всички дъщерни класове (т.е. с всички родителски и дъщерни колони), с ограничение CHECK, за да се гарантира, че дясното подмножество от полета не е NULL (т.е. две различни деца не се "смесват").
  2. „Клас бетон на маса“: Имайте различна маса за всяко дете, но няма таблица за родители. Това изисква връзките на родителите (във вашия случай Inventory <- Storage) да се повтарят във всички деца.
  3. „Клас на маса“: Да имате родителска маса и отделна маса за всяко дете, което се опитвате да направите. Това е най-чистото, но може да струва известна производителност (най-вече при промяна на данни, не толкова при запитване, защото можете да се присъедините директно от дъщерно и да пропуснете родителя).

Обикновено предпочитам 3-тия подход, но налагам и двете присъствие и ексклузивносттата на дете на ниво приложение. Налагането и на двете на ниво база данни е малко тромаво, но може да се направи, ако СУБД поддържа отложени ограничения. Например:

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

Това ще наложи както ексклузивността (поради CHECK ) и присъствието (поради комбинацията от CHECK). и FK1 /FK2 ) на детето.

За съжаление MS SQL Server не поддържа отложени ограничения, но може да успеете да „скриете“ цялата операция зад съхранени процедури и да забраните на клиентите да променят директно таблиците.

Само ексклузивността може да бъде наложена без отложени ограничения:

STORAGE_TYPE е тип дискриминатор, обикновено цяло число за спестяване на място (в примера по-горе, 0 и 1 са „известни“ на вашето приложение и се интерпретират съответно).

VAN.STORAGE_TYPE и WAREHOUSE.STORAGE_TYPE могат да бъдат изчислени (известни още като "изчислени") колони, за да се спести място за съхранение и да се избегне необходимостта от CHECK с.

--- РЕДАКТИРАНЕ ---

Изчислените колони ще работят под SQL Server по следния начин:

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".

За съжаление SQL Server изисква изчислена колона, която се използва в чужда ключ, който трябва да бъде Устойчив. Други бази данни може да нямат това ограничение (напр. виртуалните колони на Oracle), което може да спести малко място за съхранение.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Използване на DMV (изглед за динамично управление) и DMF (функция за динамично управление) | Отстраняване на проблеми с производителността на SQL Server -4

  2. Брой Брой последователни поява на стойности в табл

  3. Внедряване на отказ в MS SQL Server 2017 Standard

  4. Предотвратете запазването на промени, които изискват пресъздаване на таблицата, отрицателни ефекти

  5. Вземете знака между първите 2 специални знака в SQL