Как я понимаю, в вашем примере весь заголовок из xVariety
таблиц уникален и неприводим (KEY
). Давайте примем это, а также согласимся с тем, что мы счастливы, что таблицы находятся в 1NF
, и оставим все как есть.
Давайте также согласимся, что количество xVariety
таблиц является управляемым, скажем, менее 30 - не рекомендуется для более.
Опция 1
Это предпочтительный вариант.
Начиная с нового Variety
, супертип всех других xVariety
таблиц. VAR_ID
может быть (автоматическим приращением) целым числом, сгенерированным в (для) этой таблице; VAR_TYP
является дискриминатором.
Создайте новый {VAR_ID, VAR_TYP}
в этой таблице перед вставкой новой строки в любую из xVariety
таблиц,
-- Variety VAR_ID of type VAR_TYP exists.
--
Variety {VAR_ID, VAR_TYP}
PK {VAR_ID}
SK {VAR_ID, VAR_TYP}
CHECK (VAR_TYP IN ('Bread', 'Milk'))
xVariety
подтипы являются эксклюзивными, поэтому VAR_TYP
добавлен к каждому подтипу для лучшего контроля, примечание FK {VAR_ID, VAR_TYP}
.
MilkVariety {
VAR_ID
, VAR_TYP DEFAULT 'Milk'
, MilkType -- FullFat, Skimmed, etc
, VolumeLitres
, FatContent
, ... -- Other columns specific to this variety
}
PK {VAR_ID}
AK {MilkType, VolumeLitres, FatContent, ...}
FK {VAR_ID, VAR_TYP} REFERENCES
Variety {VAR_ID, VAR_TYP}
CHECK (VAR_TYP = 'Milk')
BreadVariety {
VAR_ID
, VAR_TYP DEFAULT 'Bread'
, BreadType -- White, WholeGrain, etc
, WeightKilos
, SugarContent
, ... -- Other columns specific to this variety
}
PK {VAR_ID}
AK {BreadType, WeightKilos, SugarContent, ...}
FK {VAR_ID, VAR_TYP} REFERENCES
Variety {VAR_ID, VAR_TYP}
CHECK (VAR_TYP = 'Bread')
Items
теперь может ссылаться Variety
.
Items { ItemID
, Name_
, Description
, CountryOfOrigin
, UseByDate
, VAR_ID
}
PK {ItemID}
FK {VAR_ID} REFERENCES Variety {VAR_ID}
Опция 2
Эта опция обеспечивает меньший контроль, но может быть проще в управлении.
Каждая таблица имеет свой независимый (автоинкремент) ID
; снова добавив VAR_TYP
для лучшего контроля.
MilkVariety {
MILK_ID
, VAR_TYP DEFAULT 'Milk'
MilkType -- FullFat, Skimmed, etc
, VolumeLitres
, FatContent
, ... -- Other columns specific to this variety
}
PK {MILK_ID}
AK {MilkType, VolumeLitres, FatContent, ...}
CHECK (VAR_TYP = 'Milk')
BreadVariety {
BREAD_ID
, VAR_TYP DEFAULT 'Bread'
BreadType -- White, WholeGrain, etc
, WeightKilos
, SugarContent
, ... -- Other columns specific to this variety
}
PK {BREAD_ID}
AK {BreadType, WeightKilos, SugarContent, ...}
CHECK (VAR_TYP = 'Bread')
Теперь view {VAR_TYP, VAR_TYP_ID}
.
-- view (logically)
--
Variety {VAR_TYP, VAR_TYP_ID}
PK {VAR_TYP, VAR_TYP_ID}
Пример:
CREATE VIEW Variety AS
SELECT VAR_TYP
, MILK_ID AS VAR_TYP_ID
FROM MilkVariety
UNION
SELECT VAR_TYP
, BREAD_ID AS VAR_TYP_ID
FROM BreadVariety ;
Обратите внимание, что представление должно UNION
всех xVariety
таблиц. Было бы хорошо, если бы мы могли (как-то) материализовать эту точку зрения, тогда она могла бы быть FK
возможной. Но, оставив это обсуждение на какое-то другое время.
Добавление {VAR_TYP, VAR_TYP_ID}
к Items
Items { ItemID
, Name_
, Description
, CountryOfOrigin
, UseByDate
, VAR_TYP
, VAR_TYP_ID
}
PK {ItemID}
-- how to implement this?
FK {VAR_TYP, VAR_TYP_ID} REFERENCES
Variety {VAR_TYP, VAR_TYP_ID}
FK
должно быть реализовано как-то . Если представление материализовано, в зависимости от СУБД, может быть возможно указать ограничение в SQL; в противном случае приложение должно позаботиться об этом.
Если xVariety
таблицы редко меняются, скажем, раз в неделю, то представление Variety {VAR_TYP, VAR_TYP_ID}
может фактически стать таблицей , Тот же процесс, который загружает xVariety
таблиц, может затем заполнить таблицу с помощью запроса. В этом случае было бы возможно иметь FK
для него из Items
.
Используйте {VAR_TYP, VAR_TYP_ID}
при объединении, чтобы не присоединиться к неправильной таблице.
SELECT *
FROM Items AS a
JOIN BreadVariety AS b ON b.VAR_TYP_ID = a.VAR_TYP_ID
AND b.VAR_TYP = a.VAR_TYP
WHERE a.CountryOfOrigin = 'US';
Примечания
All attributes (columns) NOT NULL
PK = Primary Key
AK = Alternate Key (Unique)
SK = Proper Superkey (Unique)
FK = Foreign Key