我在 BCNF 中有以下功能依赖项:
a,b -> c
a -> d
b -> d
有了附加约束,即 no a
andb
应该与 a 组合c
,其中a
andb
具有不同d
的 s。
例子:
a | d b | d a | b | c
----- ----- ---------
1 | 3 5 | 3 1 | 5 | 6
2 | 4 2 | 5 | 7
第一行a,b,c
是允许的 ( 1->3
, 5->3
),但第二行是禁止的,因为 ( 2->4
, 5->3
) 4 != 3
。
这个额外的约束可以对我的数据产生两个影响。对于每一个a,b,c
,都有两种冗余的方法来确定d
。可以有违反约束的数据。我的模式如何反映这个额外的约束?
简而言之,引入
d
第三个表以启用原始外键约束,例如 Transitional SQL-92 语法:“那么你的回答是‘不可能’吗?”
很多事情都是可能的。在您的特殊情况下,在我看来,可以通过保持数据库单表(4 列)来强制执行“附加”约束。这将保证任何组合的 a,b 将始终对应于相同的 d(因为永远只能有一个 d)。您付出的代价是,不再有一种“自然”方式(即数据库本身非常合乎逻辑的结构的直接结果)将“自动”执行您的 a->d 和 b->d FD .
众所周知,通过分解进行规范化的经典过程有时需要将某些 FD 恢复为数据库约束,因为在分解设计中,规则不能再表述为 FD。您的特殊情况似乎就是这样一种情况,您可以在“自动”执行 a->d 和 b->d 的设计之间进行选择,但是您必须付出额外的努力来执行您的附加约束,或者设计“自动”强制执行您的附加约束,但是您必须做额外的工作来强制执行 [对应于] 您的 a->d 和 b->d FD 的约束。
在您的特定情况下,使用 onedaywhen 的解决方案可以使您提到的所有约束仅由数据库结构强制执行。但是,(a)这只是针对特定情况(例如您的示例)的解决方案,(b)您付出的代价是增加了冗余,因此更新数据库时会增加额外的复杂性(并且某些更新可能无法实现!!!) ,并且(c)仍然是一个事实,即并非所有可以想象的数据库约束都可以表示为 FD。
(很抱歉发布第二个答案。我的 Stackoverflow 登录不允许我在这里发表评论。)
简而言之,创建一个
ASSERTION
确保在任何时候都不会违反业务规则的规则,例如完整标准 SQL-92 语法:坏消息是没有商业(或其他?)SQL 产品支持
CREATE ASSERTION
.大多数工业级 SQL 产品都支持触发器:可以在每个适用表的触发器中实现上述功能。MS Access 是我所知道的唯一支持
CHECK
约束子查询的商业产品,但我不认为它具有工业实力。还有其他解决方法,例如强制用户仅通过存储过程更新表,这些存储过程可以证明永远不会使数据库处于非法状态。