按照我的理解,在您的示例中,xVariety 表的整个标题是独特且不可简化的 (KEY)。让我们接受这一点,并同意我们很高兴桌子在1NF 并保留它。
让我们也同意xVariety 表的数量是可管理的,比如少于 30 个——不推荐更多。
选项 1
这是首选选项。
从新的Variety 开始,所有其他xVariety 表的超类型。
VAR_ID 可能是在(用于)此表中生成的(自动增量)整数; VAR_TYP 是鉴别器。
在任何xVariety 表中插入新行之前,在此表中创建一个新的{VAR_ID, VAR_TYP},
-- 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')
现在是一个视图 {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 必须以某种方式实现。如果视图是物化的,根据 RDBMS,可能可以在 SQL 中指定约束;否则,应用程序必须处理它。
如果xVariety 表很少更改,比如每周一次,那么视图Variety {VAR_TYP, VAR_TYP_ID} 实际上可能会变成一个表。然后,加载xVariety 表的同一进程可以使用查询填充表。在这种情况下,可以从Items 获得FK。
加入时使用{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