关于子类型的一句话。实现子类型约束的正确方法是使用断言 (CREATE ASSERTION),但它在主要数据库中仍然不可用。我改用FKs,与所有其他替代方法一样,它并不完美。人们争论很多,关于 SO 和 SE-DBA,什么更好。我也鼓励您检查其他方法。
-- Theme THM, of theme-type THM_TYP exists.
--
theme {THM, THM_TYP, -- other_common_attributes}
PK {THM}
SK {THM, THM_TYP}
CHECK THM_TYP in ('F', 'P')
-- Free theme THM (of theme-type 'F') exists.
--
free_theme {THM, THM_TYP,
-- other attributes specific to free}
PK {THM}
FK {THM, THM_TYP} REFERENCES theme {THM, THM_TYP}
CHECK (THM_TYP = 'F')
-- Paid theme THM (of theme-type 'P') exists.
--
paid_theme {THM, THM_TYP,
-- other attributes specific to paid}
PK {THM}
FK {THM, THM_TYP} REFERENCES theme {THM, THM_TYP}
CHECK (THM_TYP = 'P')
注意:
All attributes (columns) NOT NULL
PK = Primary Key
AK = Alternate Key (Unique)
SK = Proper Superkey (Unique)
FK = Foreign Key
遵循正式的规范化规则不会让您得到这个解决方案。 free_theme 和 paid_theme 表都有 FD {} --> {THM_TYP};换句话说,属性 THM_TYP 不依赖于 PK {THM},因此这些表在 2NF 中不。
在这种情况下,FK 和 CHECK 约束可防止异常和逻辑错误——这是规范化的首要目标。
如果您对不属于 2NF 的表有疑问,可以通过以下方式考虑:
- 确保 free_theme 和 paid_theme 表处于高 NF (5NF) 状态,没有
THM_TYP 属性。
- 添加
THM_TYP以便处理问题,了解妥协。
- 请记住,问题的根本原因是当前 SQL 实现中缺少所需的跨表约束(断言)。