您的披萨可以有三种配料类型:
所以我们点了两个披萨并选择以下配料:
Pizza Topping Topping Type
-------- ---------- -------------
1 mozzarella cheese
1 pepperoni meat
1 olives vegetable
2 mozzarella meat
2 sausage cheese
2 peppers vegetable
等一下,马苏里拉奶酪不能既是奶酪又是肉!香肠不是奶酪!
我们需要防止此类错误,制作马苏里拉奶酪always是奶酪。我们应该为此使用一个单独的表,因此我们只在一个地方写下该事实。
Pizza Topping
-------- ----------
1 mozzarella
1 pepperoni
1 olives
2 mozzarella
2 sausage
2 peppers
Topping Topping Type
---------- -------------
mozzarella cheese
pepperoni meat
olives vegetable
sausage meat
peppers vegetable
这是八岁孩子都能听懂的解释。这是更技术性的版本。
仅当存在多个重叠候选键时,BCNF 的行为才与 3NF 不同。
原因是函数依赖X -> Y
当然是真的,如果Y
是一个子集X
。因此,在任何只有一个候选键且处于 3NF 中的表中,它已经处于 BCNF 中,因为没有任何列(无论是键还是非键)在功能上依赖于该键之外的任何列。
因为每个披萨必须具有每种配料类型中的一种,所以我们知道 (Pizza, Topping Type) 是一个候选键。我们还直观地知道,给定的配料不能同时属于不同类型。所以 (Pizza, Topping) 必须是唯一的,因此也是一个候选键。所以我们有两个重叠的候选键。
我展示了一个异常情况,我们将马苏里拉奶酪标记为错误的配料类型。我们知道这是错误的,但导致错误的规则是依赖性Topping -> Topping Type
对于该表,这不是 BCNF 的有效依赖项。它依赖于整个候选键之外的其他东西。
因此,为了解决这个问题,我们从 Pizzas 表中取出 Topping Type,并将其设为 Toppings 表中的非键属性。