简单来说3NF和BCNF之间的区别(必须能够解释为8岁)

Arn*_*tta 148 database relational-database 3nf database-normalization

我已经阅读了引用: 数据取决于键[1NF],整个键[2NF],只有键[3NF].

但是,我无法理解3.5NF或BCNF.这是我的理解:

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

那么为什么有些3NF表不在BCNF中呢?我的意思是,3NF引用明确地说"除了密钥之外",意味着所有属性仅仅依赖于主键.毕竟,主键是候选键,直到它被选为我们的主键.

如果到目前为止我的理解有任何不妥之处,请纠正我并感谢您提供的任何帮助.

Bil*_*win 157

你的披萨可以有三种顶级类型:

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

所以我们点两个比萨饼并选择以下配料:

Pizza    Topping     Topping Type
-------- ----------  -------------
1        mozzarella  cheese
1        pepperoni   meat
1        olives      vegetable
2        mozzarella  meat
2        sausage     cheese
2        peppers     vegetable
Run Code Online (Sandbox Code Playgroud)

等一下,马苏里拉奶酪不能既是奶酪又是肉!而香肠不是奶酪!

我们需要防止这些错误,使马苏里拉奶酪永远是奶酪.我们应该为此使用一个单独的表,所以我们只在一个地方写下这个事实.

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
Run Code Online (Sandbox Code Playgroud)

这是一个8岁的孩子可能理解的解释.这是更技术性的版本.

仅当存在多个重叠候选键时,BCNF与3NF的行为不同.

原因是如果函数依赖是其子集,则函数依赖性X -> Y当然是正确Y的X.因此,在任何只有一个候选键并且在3NF中的表中,它已经在BCNF中,因为没有列(键或非键)在功能上依赖于除该键之外的任何东西.

因为每个披萨必须具有每种顶部类型中的一种,我们知道(Pizza,Topping Type)是候选键.我们也直观地知道给定的浇头不能同时属于不同的类型.因此(Pizza,Topping)必须是唯一的,因此也是候选键.所以我们有两个重叠的候选键.

我展示了一个异常,我们将mozarella标记为错误的浇头类型.我们知道这是错误的,但是错误的规则是依赖关系Topping -> Topping Type,它不是BCNF对此表的有效依赖关系.它是对整个候选键之外的其他东西的依赖.

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

  • "所以在任何只有一个候选键并且在3NF中的表中" - 不完全相同.您提供的示例符合此条件.但是,它不是3NF的例子,因为它不是2NF.密钥(1NF),整个密钥(2NF),只有密钥(3NF).关键是(Pizza,Topping),ToppingType列依赖于键而不是键,但它不依赖于整个键.因此它不是2NF,因此不是3NF或BCNF.这是1NF.使其成为2NF将绕过您试图说明的问题. (12认同)
  • 对不起,我不得不将其投票.您展示的示例不在3NF中.为了理解BCNF的目的,我必须看到一个例子,它在3NF但不是BCNF.现在,我没有看到BCNF的目的. (5认同)
  • 为什么不在2NF处理?从我的观点来看,原始表的主键是Pizza + Topping,而Topping Type依赖于Topping,那么在2NF阶段应该注意的是部分依赖吗? (5认同)
  • @DanielBarbalace,此表的要点是它具有此表的备用候选键:(Pizza,ToppingType)。由于ToppingType是该候选密钥的子集,因此满足2NF。 (4认同)
  • "这是对整个候选键以外的东西的依赖." - 谢谢 (3认同)
  • @DanielBarbalace 2NF违规的特征可以是当CK部分确定* non-prime *(也称为non-CK)属性时。但是这里所有的属性都是主要的。因此,不能违反2NF。另外,如果您不知道,您也不会引用1NF,2NF或3NF的定义。 (2认同)

nvo*_*gel 87

细微差别在于3NF区分了键和非键属性(也称为非素数属性),而BCNF则没有.

使用Zaniolo对3NF 的定义可以得到最好的解释,这相当于Codd的:

对于R满足的每个非平凡FD(X-> A),满足下列条件中的至少一个条件的关系R为3NF:

(a)X是R的超级密钥,或

(b)A是R的关键属性

BCNF要求(a)但不将(b)视为其自身的特殊情况.换句话说,BCNF要求每个重要的决定因素都是超级密钥,即使其依赖属性恰好是密钥的一部分.

关系R在BCNF中如果对于满足R的每个非平凡FD(X-> A),则满足以下条件:

(a)X是R的超级密钥

因此BCNF更严格.

差异是如此微妙,许多人非正式地描述为3NF实际上是BCNF.例如,你在这里说3NF意味着"数据取决于密钥[s] ......除了密钥[s]之外什么都没有",但这实际上是BCNF的非正式描述而不是3NF.3NF可以更准确地描述为" 非关键数据取决于密钥...而且只有密钥".

你还说:

3NF引用明确地说"除了关键",意味着所有属性仅依赖于主键.

这太过于简单化了.3NF和BCNF以及所有正常表格都关注所有候选键和/或超级键,而不仅仅是一个"主键".

  • R {A,B,C}其中{A,B}是关键.给定依赖性C-> B,R满足3NF但不满足BCNF的要求. (10认同)
  • 哇.Zaniolo教授实际上教我的课程(CS 143,加州大学洛杉矶分校),我在准备期末考试时偶然发现了这个答案.很高兴看到我教授的名字,并感谢您的详细解答! (6认同)
  • 如果属性是任何候选键的一部分,则属性为素数; 非素数,如果它不是任何候选键的一部分. (3认同)
  • 密钥表示候选密钥.Key*属性*表示属于候选键的属性,AKA a*prime属性*. (2认同)

AGé*_*der 23

BCNF和3NF之间的区别

使用BCNF定义

当且仅当对于它的每个依赖关系X→Y时,至少有下列条件之一:

  • X→Y是一个平凡的函数依赖(Y⊆X),或
  • X是架构R的超级密钥

和3NF的定义

当且仅当对于其每个功能依赖关系X→A时,至少下列条件之一成立:

  • X包含A(即,X→A是平凡的函数依赖),或
  • X是超级钥匙,或
  • AX的每个元素(A和X之间的集合差异)是主要属性(即,AX中的每个属性都包含在某个候选键中)

我们看到以下差异,简单来说:

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

而

  • 在3NF中:部分键(主要属性)也可以依赖于不是超级键的属性(即另一个部分键/素数属性或甚至非素数属性).

哪里

  1. 一个主属性是一个候选键找到一个属性,
  2. 一个候选键是该关系的最小的超密钥,并
  3. 甲超密钥是一组的关系可变的属性的用于其保持在分配给该变量的所有关系,不存在两个不同的元组具有在此set.Equivalently一个超密钥对的属性相同的值(行)也可以被定义为关系模式的一组属性,模式的所有属性在功能上都依赖于这些属性.(超级键总是包含候选键/候选键始终是超级键的子集.您可以在关系中添加任何属性以获取其中一个超级键.)

也就是说,候选键的任何部分子集(除了全集之外的任何非平凡子集)都可以在功能上依赖于除超级密钥之外的任何其他东西.

不在BCNF中的表/关系受到异常的影响,例如另一个用户在比萨示例中提到的更新异常.不幸,

  • BNCF 不能总是获得,而
  • 总能获得3NF.

3NF与BCNF示例

目前可以在维基百科上的" 3NF表不符合BCNF(Boyce-Codd普通形式) "中找到差异的示例,其中下表符合3NF但不符合BCNF,因为"网球场"(部分键/主要属性)取决于在"Rate Type"(一个不是超级键的部分键/素数属性)上,这是我们可以通过询问数据库的客户,网球俱乐部来确定的依赖:

今天的网球场预订(3NF,不是 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
Run Code Online (Sandbox Code Playgroud)

该表的超级键是:

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
Run Code Online (Sandbox Code Playgroud)

3NF问题:部分键/素数属性"Court"依赖于超级键以外的其他内容.相反,它取决于部分键/素数属性"速率类型".这意味着如果我们升级法院,用户必须手动更改费率类型,或者如果想要应用费率更改,则手动更改法院.

  • 但是,如果用户升级法院但不记得提高费率怎么办?或者如果错误的费率类型适用于法院怎么办?

(在技术方面,我们不能保证不会违反"费率类型" - >"法院"功能依赖.)

BCNF解决方案:如果我们想将上表放在BCNF中,我们可以将给定的关系/表分解为以下两个关系/表(假设我们知道费率类型仅取决于法院和成员身份,我们可以通过询问我们的数据库的客户,网球俱乐部的所有者发现:

费率类型(BCNF和较弱的3NF,BCNF暗示)

Rate Type   Court   Member Flag
---------   -----   -----------
SAVER       1       Yes
STANDARD    1       No
PREMIUM-A   2       Yes
PREMIUM-B   2       No
Run Code Online (Sandbox Code Playgroud)

今天的网球场预订(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
Run Code Online (Sandbox Code Playgroud)

解决的问题:现在,如果我们升级法院,我们可以保证费率类型将反映这一变化,我们不能为法院收取错误的价格.

(在技术方面,我们可以保证不会违反功能依赖"费率类型" - >"法院".)


jfe*_*ard 11

这是一个老问题,有很有价值的答案,但我仍然有点困惑,直到我找到一个现实生活中的例子来显示 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 
Run Code Online (Sandbox Code Playgroud)

每个房间只有一名老师,而且他们从不移动。如果您看一下,您会发现: (1) 对于每个属性Teacher, Date, Room,每行只有一个值。(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
Run Code Online (Sandbox Code Playgroud)

我们可以得出什么结论?(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
Run Code Online (Sandbox Code Playgroud)

和

Teacher   | Room
----------|-----
Mr Smith  | A12
Mr Jones  | B10
Ms Doe    | C21
Ms Rogers | A08
Run Code Online (Sandbox Code Playgroud)

但 3NF 不处理素数属性依赖性。这就是问题所在:在某些情况下,3NF 合规性不足以确保良好的表模式设计。

使用 BCNF,您不必关心该属性是否是 2NF 和 3NF 规则中的素数属性。对于每个非平凡的依赖关系(子集显然是由它们的超集决定的),行列式是一个完整的超级键。换句话说,除了完整的超级密钥(不包括琐碎的 FD)之外,没有任何东西是由其他东西决定的。(有关正式定义,请参阅其他答案)。

一旦Room取决于Teacher,Room必须是Teacher(事实并非如此) 或Teacher必须是超级键(我的日记中不是这种情况,但拆分表时就是这种情况)。

总结一下:BNCF 比 3NF 更严格,但在我看来更容易掌握:

  • 在大多数情况下,BCNF 与 3NF 相同;
  • 在其他情况下,BCNF 就是您所认为/希望的 3NF。


sma*_*007 6

所有的好答案。简而言之 [BCNF] 没有部分密钥可以依赖于密钥。

即,候选键的任何部分子集(即,除完整集外的任何非平凡子集)都不能在功能上依赖于某个候选键。

  • 为什么不?假设有一个关系 R(A, B, C, D, E) 和 (A, B) 和 (C, D) 是候选键。然后AB-> D。由于AB是R的超键,所以R应该在BCNF中,对吧?(只是一个问题,试图理解这一点。) (2认同)

KGh*_*tak 5

\xe2\x80\x98 smartnut007 \xe2\x80\x99、\xe2\x80\x98 Bill Karwin \xe2\x80\x99 和 \xe2\x80\x98 sqlvogel \xe2\x80\x99 的答案非常好。不过,让我提出一个有趣的观点。

\n\n

嗯,我们有主键和非主键。

\n\n

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

\n非素数可以是相关的,也可以不是。

\n\n
    \n
  • 当依赖时:我们看到它们必须依赖于完整的候选键。这是2NF。
  • \n
  • 当不依赖时:可以存在无依赖或传递依赖

    \n\n
      \n
    • 甚至没有传递依赖:不确定什么规范化理论可以解决这个问题。
    • \n
    • 当传递依赖时:这被认为是不可取的。这就是3NF。
    • \n
  • \n
\n\n

素数之间的依赖关系又如何呢?

\n现在你看,我们\xe2\x80\x99并没有通过第二个或第三个NF来解决素数之间的依赖关系。\n进一步的这种依赖关系(如果有的话)是不可取的,因此我们\xe2\x80\x99有一个单一的规则来解决这个问题。这就是BCNF。

\n\n

参考Bill Karwin的帖子中的示例,您\xe2\x80\x99 会注意到 \xe2\x80\x98 Topping \xe2\x80\x99 和 \xe2\x80\x98 Topping Type \xe2\x80\ x99 是主键并且具有依赖性。如果它们是有依赖性的非素数,那么 3NF 就会开始发挥作用。

\n\n

笔记:

\n BCNF 的定义非常通用,并且没有区分素数和非素数的属性。然而,上述思维方式有助于理解即使在第二次和第三次 NF 之后,某些异常是如何渗透的。

\n\n

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

\n现在我们知道 BCNF 提供了一个通用定义,而不涉及任何素数/非素数属性,让我们看看 BCNF 和 2/3 NF 是如何相关的。

\n首先,BCNF 要求(除了微不足道的情况)对于每个功能依赖X -> Y(FD),X 应该是超级键。\n如果您只考虑任何 FD,那么我们有三种情况 - (1) X 和 Y非素数,(2) 两者都是素数,并且 (3) X 素数和 Y 非素数,丢弃(无意义的)情况 X 非素数和 Y 素数。

\n对于情况 (1),3NF 负责处理。

\n对于情况 (3),由 2NF 处理。

\n对于情况(2),我们发现BCNF的使用

\n