在简单的说法中,第三范式(3NF)和巴斯-科德范式(BCNF)有什么区别?(必须能够向一个8岁的孩子解释)

185
我已阅读过这段引文:数据取决于键[1NF]、整个键[2NF]和仅仅是键[3NF]

然而,我有困难理解3.5NF或称为BCNF。以下是我所理解的:

  • BCNF比3NF更严格
  • 表中任何FD的左侧必须是超键(或至少是候选键)

那么为什么有些3NF表格不符合BCNF呢?我的意思是,3NF引言明确表示“仅仅是键”,这意味着所有属性仅依赖于主键。毕竟,主键在被选择为我们的主键之前是一个候选键。

如果我对目前的理解有误,请纠正我,并感谢您提供的任何帮助。


3
你认为非教科书来源的信息是从哪里得来的?很多教科书也很糟糕,但教科书会由多个有学术经验的人审查,并且比其他人对教科书的解释更不可能是无稽之谈。未经了解和有误导性的人给出的高评价并不能证明其正确性。我在那里留下了这条评论是为了给看到你的问题的人提供帮助。那句“只有关键点”的话毫无用处。正确的定义肯定是个问题,因为没有一个正确的定义,“理解概念”是不可能的。 - philipxy
6个回答

179

你的披萨只能选择三种配料中的一种:

  • 一种奶酪
  • 一种肉类
  • 一种蔬菜

所以我们点了两个披萨并选择了以下配料:

Pizza    Topping     Topping Type
-------- ----------  -------------
1        mozzarella  cheese
1        pepperoni   meat
1        olives      vegetable
2        mozzarella  meat
2        sausage     cheese
2        peppers     vegetable

等等,马苏里拉干酪既不能是奶酪也不能是肉!香肠也不是奶酪!

我们需要防止这些错误,让马苏里拉干酪始终是奶酪。我们应该使用一个单独的表格来实现这一点,这样我们只需在一个地方写下这个事实。

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

这是一个适合8岁孩子理解的解释。以下是更加技术性的版本。

仅当存在多个重叠的候选键时,BCNF才会与3NF有所不同。

原因在于,如果YX的子集,则功能依赖关系X -> Y显然成立。因此,在任何具有唯一候选键并且处于3NF中的表中,它已经在BCNF中,因为除了该键之外没有任何列(键或非键)是在功能上依赖于其他任何东西的。

因为每个披萨必须恰好拥有每种配料类型的其中之一,我们知道(Pizza,Topping Type)是一个候选键。我们也可以直观地知道,给定的配料不能同时属于不同的类型。因此,(Pizza,Topping)必须是唯一的,因此也是一个候选键。因此,我们有两个重叠的候选键。

我展示了一个异常情况,我们将mozarella标记为错误的配料类型。我们知道这是错的,但使其出错的规则是一种依赖关系Topping -> Topping Type,对于此表格来说,它不是一种有效的BCNF依赖关系。这是对整个候选键之外的某些东西的一种依赖。

因此,要解决这个问题,我们将Topping Type从Pizzas表中取出,并将其作为非键属性放入Toppings表中。


5
“它是对非整个候选键的某些其他内容的依赖。” - 谢谢 - gnsb
15
"因此,在任何只有一个候选键且符合第三范式的表中" - 不完全正确。您提供的示例确实符合此条件,但它不是3NF示例,因为它不是2NF。关键是(1NF),整个关键是(2NF),只有关键是(3NF)。关键是(Pizza,Topping),而ToppingType列依赖于关键且仅依赖于关键,但它不依赖于整个关键。因此它不是2NF,因此也不是3NF或BCNF。它是1NF。使其成为2NF将绕过您试图说明的问题。" - Daniel Barbalace
6
这个表的重点在于它有一个备选键:(Pizza,ToppingType)。由于ToppingType是该备选键的子集,因此它满足第二范式(2NF)。 - Bill Karwin
12
抱歉我不得不投反对票。你展示的例子不符合第三范式(3NF)。为了理解BCNF的目的,我必须看到一个在3NF中但不符合BCNF的例子。现在,我还没有看到BCNF的意义。 - Spero
6
为什么这个问题在2NF中没有得到解决?从我的角度来看,原始表的主键是Pizza+Topping,而Topping Type依赖于Topping,这不是一个部分依赖关系吗?应该在2NF阶段解决这个问题才对吧? - GreenPenguin
显示剩余6条评论

100
细微的差别在于第三范式(3NF)区分关键属性和非关键属性(也称为非主属性),而BCNF则不区分。
最好使用Zaniolo's definition中的3NF定义来解释,这与Codd的定义等效:
关系R在至少满足一个以下条件的情况下是在3NF中: (a) X是R的超键,或者 (b) A是R的关键属性
BCNF要求(a),但不将(b)视为它自己的特殊情况。换句话说,BCNF要求每个非平凡决定因素都是超键,即使其依赖属性恰好是键的一部分。
关系R在满足以下条件的情况下是在BCNF中: (a) X是R的超键
因此,BCNF更加严格。
差异是如此微小,以至于许多人非正式地描述3NF实际上是BCNF。例如,您在此处声明3NF意味着“数据取决于键...除了键之外没有其他内容”,但这实际上是BCNF的非正式描述,而不是3NF。 3NF可以更准确地描述为“非键数据取决于键...除了键之外没有其他内容”。

您还提到:

第三范式的引用明确表示“只有键”,这意味着所有属性仅依赖于主键。

那是一种过度简化。第三范式、BCNF和所有范式都关注所有候选键和/或超键,而不仅仅是一个“主”键。


11
哇,Zaniolo教授实际上是我(CS 143, UCLA)的课堂老师,我在为期末考试做准备时偶然发现了这个答案。看到我的教授的名字感到很高兴,感谢您提供详细的答案! - DV.
你能举一个在第三范式但不在BCNF的关系的例子吗?我很难想象... - Leo
11
给定依赖关系C->B,其中{A,B}是一个键。R满足第三范式的要求但不符合BCNF。 - nvogel
2
关键字意味着候选键。关键字属性是候选键的一部分,也称为主属性 - nvogel
4
如果一个属性是任何候选键的一部分,那么它是主属性;如果它不是任何候选键的一部分,那么它是非主属性。 - nvogel
显示剩余4条评论

39

BCNF与3NF之间的区别

使用BCNF定义

当且仅当对于其依赖关系X → Y,至少满足以下条件之一时:

  • X → Y是平凡函数依赖(Y⊆X),或者
  • X是模式R的超键。

和3NF定义

当且仅当对于其每个功能依赖项X → A,至少满足以下条件之一:

  • X包含A(即,X → A是平凡函数依赖项)或者
  • X是超键或者
  • A-X,即A和X之间的差集中的每个元素都是主属性(即,A-X中的每个属性都包含在某些候选键中)

我们看到以下简单差异:

  • 在BCNF中:每个部分键(主属性)只能依赖于超键,

  • 在3NF中:部分键(主属性)还可以依赖于一个不是超键的属性(即另一个部分键/主属性甚至是非主属性)。

其中

  1. 主属性是在候选键中找到的属性,而
  2. 候选键是该关系的最小超键,而
  3. 超键是一个关系变量的属性集,在该变量分配的所有关系中,这个集合的属性值没有两个不同的元组(行)具有相同的值。等价地,可以将超键定义为满足所有关系架构属性都存在功能依赖关系的关系架构属性集。 (超键始终包含候选键/候选键始终是超键的子集。您可以添加任何属性以获得其中之一超键。)

也就是说,候选键的任何非平凡子集(除了完整集)都不能依赖于任何东西,除了超键。

不符合BCNF的表/关系会面临异常情况,例如另一位用户在披萨示例中提到的更新异常。不幸的是,

  • BNCF 无法始终获得,而
  • 3NF 始终可以获得

3NF与BCNF示例

目前可以在维基百科的“ 3NF表未达到BCNF(Boyce-Codd正则化形式)”中找到差异示例,其中以下表符合3NF但不符合BCNF,因为“网球场”(部分键/主属性)取决于“费率类型”(不是超键的部分键/主属性),这是我们可以通过询问数据库的客户-网球俱乐部来确定的依赖关系:

今天的网球预订 ( 3NF, not BCNF )

Court   Start Time  End Time    Rate Type
------- ----------  --------    ---------
1       09:30       10:30       SAVER
1       11:00       12:00       SAVER
1       14:00       15:30       STANDARD
2       10:00       11:30       PREMIUM-B
2       11:30       13:30       PREMIUM-B
2       15:00       16:30       PREMIUM-A

表的超键为:

S1 = {Court, Start Time}
S2 = {Court, End Time}
S3 = {Rate Type, Start Time}
S4 = {Rate Type, End Time}
S5 = {Court, Start Time, End Time}
S6 = {Rate Type, Start Time, End Time}
S7 = {Court, Rate Type, Start Time}
S8 = {Court, Rate Type, End Time}
ST = {Court, Rate Type, Start Time, End Time}, the trivial superkey

第三范式问题: 部分键/主属性"Court"依赖于非超键的其他内容。相反,它依赖于部分键/主属性"Rate Type"。这意味着如果我们升级一个球场,则用户必须手动更改费率类型,或者如果想要应用费率更改则必须手动更改球场。

  • 但是,如果用户升级了球场,但忘记增加费率怎么办?或者如果将错误的费率类型应用于球场会怎么样呢?

(从技术角度来看,我们无法保证“费率类型” -> “球场”函数依赖关系不会被违反。)

BCNF解决方案: 如果我们希望将上述表放入BCNF,则可以将给定的关系/表分解为以下两个关系/表(假设我们知道费率类型仅取决于球场和会员身份状态,这可以通过询问我们数据库的客户,即网球俱乐部的所有者来发现):

费率类型BCNF和较弱的3NF,由BCNF隐含)

Rate Type   Court   Member Flag
---------   -----   -----------
SAVER       1       Yes
STANDARD    1       No
PREMIUM-A   2       Yes
PREMIUM-B   2       No

今日网球场预订BCNF和较弱的3NF,这是由BCNF暗示的)

Member Flag     Court     Start Time   End Time
-----------     -----     ----------   --------
Yes             1         09:30        10:30
Yes             1         11:00        12:00
No              1         14:00        15:30
No              2         10:00        11:30
No              2         11:30        13:30
Yes             2         15:00        16:30

问题已解决: 现在,如果我们升级球场,我们可以确保费率类型将反映这种更改,并且我们不会对球场收取错误的价格。

(从技术上讲,我们可以保证功能依赖关系“费率类型” -> “球场”不会被违反。)


9

这是一个有价值回答的老问题,但我仍然有些困惑,直到我发现了一个真实的例子,展示了3NF存在的问题。也许不适合8岁的孩子,但希望它有所帮助。

明天我将在一次季度家长/教师会议上与我大女儿的老师们见面。以下是我的日记内容(姓名和房间已更改):

Teacher   | Date             | Room
----------|------------------|-----
Mr Smith  | 2018-12-18 18:15 | A12 
Mr Jones  | 2018-12-18 18:30 | B10 
Ms Doe    | 2018-12-18 18:45 | C21 
Ms Rogers | 2018-12-18 19:00 | A08 

每个房间只有一个老师,他们不会移动。如果您仔细观察,您会发现: (1) 对于每个属性TeacherDateRoom,我们每行只有一个值。 (2) 超键包括:(Teacher, Date, Room)(Teacher, Date)(Date, Room),而候选键显然是(Teacher, Date)(Date, Room)

(Teacher, Room)不是超键,因为我下个季度将完成表格,并可能有这样一行(史密斯先生没有移动!):

Teacher  | Date             | Room
---------|------------------| ----
Mr Smith | 2019-03-19 18:15 | A12

我们能得出什么结论?(1)是非正式但正确的1NF表述。从(2)我们可以看到,没有“非主属性”:2NF和3NF是免费提供的。
我的日记是3NF。很好!不,不是真的,因为没有数据建模者会在数据库模式中接受这个。Room属性依赖于Teacher属性(再次强调:老师不会搬家!),但模式没有反映这一事实。一个理智的数据建模者会做什么?将表拆分成两个:
Teacher   | Date
----------|-----------------
Mr Smith  | 2018-12-18 18:15
Mr Jones  | 2018-12-18 18:30
Ms Doe    | 2018-12-18 18:45
Ms Rogers | 2018-12-18 19:00

并且

Teacher   | Room
----------|-----
Mr Smith  | A12
Mr Jones  | B10
Ms Doe    | C21
Ms Rogers | A08

但是,第三范式并不能解决主属性依赖的问题。这就是问题所在:在某些情况下,仅满足第三范式的要求并不足以确保表格模式设计合理。
使用BCNF时,你不需要关心属性在2NF和3NF规则中是否为主属性。对于每个非平凡依赖(子集显然由它们的超集确定),决定因素是完整的超键。换句话说,除了平凡的函数依赖外,没有任何东西是由其他东西而不是完整的超键来确定的。(请参见其他答案以获取正式定义)。
一旦“Room”依赖于“Teacher”,“Room”必须是“Teacher”的子集(这不是情况)或者“Teacher”必须是超键(这在我的日记中不是情况,但是在拆分表格时是情况)。
总之,BCNF比第三范式更严格,但在我看来更容易理解:
- 在大多数情况下,BCNF与第三范式相同; - 在其他情况下,BCNF就是你认为/希望第三范式是什么。

7

所有的答案都很好。简单来说,[BCNF]没有任何部分键可以依赖于关键字。

例如,候选键的任何非平凡子集(即除全集之外的任何子集)都不能在某些候选键上具有函数依赖性。


2
为什么不呢?假设有一个关系R(A,B,C,D,E),其中(A,B)和(C,D)是候选键。那么AB->D。由于AB是R的超键,所以R应该在BCNF中,对吧?(只是一个问题,想要理解这个。) - peteykun

5

smartnut007’、‘Bill Karwin’和‘sqlvogel’的回答都很好。但是让我提出一个有趣的观点。

我们有主键和非主键。

当我们关注非主键如何依赖于主键时,我们会看到两种情况:

非主键可以依赖或不依赖

  • 当依赖时:我们看到它们必须依赖于完整候选键。这是2NF
  • 当不依赖时:可能没有依赖或传递依赖

    • 甚至没有传递依赖:不确定规范化理论如何解决此问题。
    • 当存在传递依赖时:被认为是不可取的。这是3NF

那么主键之间的依赖关系呢?

现在你看到了,我们既不通过第二范式也不通过第三范式来处理主键之间的依赖关系。 此外,如果有任何这样的依赖关系,则不可取,因此我们有一个单一的规则来解决这个问题。这是BCNF

参考Bill Karwin在这里发布的示例,您将注意到‘Topping’和‘Topping Type’都是主键并具有依赖关系。如果它们是具有依赖关系的非主键,则3NF将会发挥作用。

注意:

BCNF的定义非常通用,没有区分主键和非主键属性。然而,上述思考方式有助于理解即使在第二范式和第三范式之后某些异常如何传播。

高级话题:将通用BCNF映射到2NF和3NF

现在我们知道BCNF提供了一个通用的定义,没有引用任何主/非主属性,让我们看看BCNF和2/3 NF之间的关系。

首先,BCNF要求(除了微不足道的情况外),对于每个函数依赖X -> Y(FD),X应该是超键。 如果只考虑任何FD,则我们有三种情况 - (1)X和Y都是非主键,(2)都是主键和(3)X是主键而Y是非主键,舍弃(无意义的)X是非主键而Y是主键的情况。

对于情况(1),3NF可以处理。

对于情况(3),2NF可以处理。

对于情况(2),我们发现使用BCNF。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接