Опростете изграждането на MATCH SIMPLE
поведение на fk ограничения
Ако поне една колона от многоколонно чуждо ограничение с MATCH SIMPLE
по подразбиране поведението е NULL
, ограничението не се прилага. Можете да надграждате върху това, за да опростите значително своя дизайн.
CREATE SCHEMA test;
CREATE TABLE test.status(
status_id integer PRIMARY KEY
,sub bool NOT NULL DEFAULT FALSE -- TRUE .. *can* be sub-status
,UNIQUE (sub, status_id)
);
CREATE TABLE test.entity(
entity_id integer PRIMARY KEY
,status_id integer REFERENCES test.status -- can reference all statuses
,sub bool -- see examples below
,additional_col1 text -- should be NULL for main entities
,additional_col2 text -- should be NULL for main entities
,FOREIGN KEY (sub, status_id) REFERENCES test.status(sub, status_id)
MATCH SIMPLE ON UPDATE CASCADE -- optionally enforce sub-status
);
Той е много евтин за съхраняване на някои допълнителни NULL колони (за основни обекти):
Между другото, по документация:
Демонстрационни данни:
INSERT INTO test.status VALUES
(1, TRUE)
, (2, TRUE)
, (3, FALSE); -- not valid for sub-entities
INSERT INTO test.entity(entity_id, status_id, sub) VALUES
(11, 1, TRUE) -- sub-entity (can be main, UPDATES to status.sub cascaded)
, (13, 3, FALSE) -- entity (cannot be sub, UPDATES to status.sub cascaded)
, (14, 2, NULL) -- entity (can be sub, UPDATES to status.sub NOT cascaded)
, (15, 3, NULL) -- entity (cannot be sub, UPDATES to status.sub NOT cascaded)
SQL Fiddle (включително вашите тестове).
Алтернатива с един FK
Друг вариант е да въведете всички комбинации от (status_id, sub)
в status
таблица (може да има само 2 на status_id
) и имат само едно fk ограничение:
CREATE TABLE test.status(
status_id integer
,sub bool DEFAULT FALSE
,PRIMARY KEY (status_id, sub)
);
CREATE TABLE test.entity(
entity_id integer PRIMARY KEY
,status_id integer NOT NULL -- cannot be NULL in this case
,sub bool NOT NULL -- cannot be NULL in this case
,additional_col1 text
,additional_col2 text
,FOREIGN KEY (status_id, sub) REFERENCES test.status
MATCH SIMPLE ON UPDATE CASCADE -- optionally enforce sub-status
);
INSERT INTO test.status VALUES
(1, TRUE) -- can be sub ...
(1, FALSE) -- ... and main
, (2, TRUE)
, (2, FALSE)
, (3, FALSE); -- only main
И т.н.
Свързани отговори:
- MATCH FULL срещу MATCH SIMPLE
- Ограничение за външен ключ с две колони само когато третата колона НЕ е NULL
- Проверка на уникалност в база данни, когато проверката има условие за друга таблица
Запазване на всички таблици
Ако имате нужда от всичките четири таблици по някаква причина, която не е във въпроса, разгледайте това подробно решение на много подобен въпрос на dba.SE:
Наследяване
... може да е друга опция за това, което описвате. Ако можете да живеете с някои основни ограничения . Свързан отговор: