我最近了解了 1NF、2NF 和 3NF。我了解定义和差异。我之前还了解到通过使用桥接 1:M 实体从概念模型中删除 M:M 关系(但当时我不知道正常形式)。我现在看到的关于规范化的很酷的事情是,如果你从一个大的混乱关系开始,规范化步骤会自动为你处理 M:M,所以你不必有意识地认为“好吧,我正在桥接我的毫米。”
但是,我决定假设性地问自己哪个级别的规范化专门负责删除 M:M 关系。我知道它不是 1NF,因为我可以很容易地想出 1NF 和 M:M 的例子。但是,在我设计的所有简单示例中,将它们引入 2NF 使 M:M 消失了。但是,我不确定这是确定的,因为我在想出详尽的例子方面似乎不是很有创意。所以我提出这个问题:是否存在存在并且仍然是 M:M 的 2NF 关系,它需要通过 3NF 才能删除 M:M?还是 2NF 本身一直不允许 M:M?
谢谢!
更新:让我试着更好地解释自己。考虑这个简单的例子:
表 BOOK_AUTHOR
| ISBN | Title | AuthorID | AuthorName|
|------------|-----------|-----------|-----------|
| 0001 | Book1 | A01 | King |
| 0001 | Book1 | A02 | Tolkien |
| 0002 | Book2 | A01 | King |
| 0003 | Book3 | A02 | Tolkien |
|------------|-----------|-----------|-----------|
Run Code Online (Sandbox Code Playgroud)
这是在 1NF 中,PK 是 {ISBN, AuthorID}。
要转到 2NF,我们删除部分依赖项 ISBN->Title 和 AuthorID->AuthorName 并最终得到:
BOOK_AUTHOR (ISBN, AuthorID)
BOOK (ISBN, Title)
AUTHOR (AuthorID, AuthorName)
Run Code Online (Sandbox Code Playgroud)
现在我们有两个真正的“实体”表,BOOK 和 AUTHOR,加上人工桥实体 BOOK_AUTHOR。我们只是通过去2NF到达那里。
但是,如果我以不同的方式开始并使用 BOOK 和 AUTHOR 以及它们之间的 M:M 关系创建 ER,我将不得不自己创建人工 BOOK_AUTHOR 表,这在上面的 2NF 时自动发生。我的问题:它是否总是发生在 2NF,或者您有时需要到达 3NF 来创建桥接?
然而,现在我把我自己的问题更清楚了,我想我看到了一个巨大的错误。我问的是桥是在哪个 xNF 上创建的,但事实是我上面的 1NF 示例只不过是一座巨大的桥。进入 2NF 并不会“创建桥梁”......它更像是通过将真实实体从虚假的巨大桌子中拉出而在桥的两侧创建土地。因此,使用 2NF(和更高版本)似乎与桥接无关,而更多是关于消除数据冗余(这当然是它首先呈现给我的方式)!
小智 8
正常形式与多对多关系没有任何关系。如果您碰巧丢失了一些作为规范化过程的副产品,那很好,但您通常不会这样做。如果我们考虑到我们有两个表:Salesman 和 Product,它们每个都有 ID 字段作为它们的主键,我们还有一个名为 Specializes 的表,它显示哪些 Salesmen 专门销售哪些产品。这个 Specializes 表将代表多对多关系,因为每个销售员可以专门从事多种产品,并且每种产品可以由多个销售人员专门从事。它可能看起来像这样(原谅尴尬的格式,我们不能在 StackExchange 上做真正的表格):
| SalesmanID | ProductID |
|------------|-----------|
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
| 2 | 2 |
| 2 | 3 |
|------------|-----------|
Run Code Online (Sandbox Code Playgroud)
显然,缺少空值和重复行意味着该表在 1NF 中。在此表中,唯一的候选键是 {SalesmanID, ProductID},因此没有非主要属性。它还不包含重要的函数依赖项。因此,它必然在 2NF、3NF 和 BCNF 中。我还将在没有证据的情况下断言它属于 4NF、5NF、6NF 和 DKNF(以避免必须解释其中的所有细节)。因此,实际上,没有任何范式可以消除多对多关系,也不是有意这样做的。范式的目的不是删除多对多关系(我实际上不清楚您为什么要这样做),而是删除潜在的插入异常、更新异常和删除异常。范式的主要作用是确保每条信息在数据库表中精确表示一次。在多个地方嵌入相同的信息会导致问题。但这与多对多关系无关。
我认为您的意思是问一个稍微不同的问题,例如将多对多关系嵌入到还尝试包含其他信息的表中的情况,例如上面的表是否包含产品名称以及产品编号(其中名称在功能上由编号决定)。像这样的表要么违反 2NF(如果名称在功能上也没有确定数字)或 Boyce Codd 范式(如果名称在功能上确定了数字)。
您也可能会考虑不同的情况:当我们在同一个表中有两个不相关的 1:M 关系时,例如如果我们要添加第三列来标识每个销售员使用的语言。
| SalesmanID | ProductID | Language |
|------------|-----------|----------|
| 1 | 1 | English |
| 1 | 2 | English |
| 2 | 1 | Spanish |
| 2 | 2 | Spanish |
| 2 | 3 | Spanish |
| 2 | 1 | French |
| 2 | 2 | French |
| 2 | 3 | French |
|------------|-----------|----------|
Run Code Online (Sandbox Code Playgroud)
如您所见,该表存在很大问题,因为我们需要 6 个条目来表示销售员 2 专门从事 3 种产品并会说 2 种语言。这是第四范式违规。
编辑:
澄清后,很明显他要问的是像 Specializes 表这样的表,但是有关于销售人员和产品的额外信息,本质上是一个包含两个实体集和它们在单个表中的多对多关系的表. 所以要直接回答这个问题,是的,你可以有像 3NF 那样的糟糕表格。保证不会发生这种情况的范式是博伊斯-科德范式 (BCNF)。这是一个糟糕的表的例子,它容易受到各种异常(插入、更新和删除)的影响,但属于 2NF 和 3NF。
| SalesmanName | SalesmanID | ProductID | ProductName |
|--------------|------------|-----------|-------------|
| Alex | 1 | 1 | Thingy |
| Alex | 1 | 2 | Whatsit |
| Barb | 2 | 1 | Thingy |
| Barb | 2 | 2 | Whatsit |
| Barb | 2 | 3 | Whoosit |
|--------------|------------|-----------|-------------|
Run Code Online (Sandbox Code Playgroud)
所以,看看这张表,它显然是在 1NF 中。此外,我们可以非常直接地识别非平凡的函数依赖关系。销售员姓名 -> 销售员 ID。销售员 ID -> 销售员姓名。产品 ID -> 产品名称。产品名称 -> 产品 ID。接下来我们需要识别候选键。有四个:{SalesmanName,ProductID}、{SalesmanName,ProductName}、{SalesmanID, ProductID} 和 {SalesmanID, ProductName}。因此,我们没有非素数属性。因此,我们必然处于 2NF(非主要属性之间没有函数依赖关系)和 3NF(没有非平凡函数依赖关系,其中左侧不是超级键,右侧包含非主要属性) . 然而,我们不在 BCNF 中,因为确实存在非平凡的函数依赖,其左侧不是超键。
任何类似的情况也永远不会是 Boyce-Codd 范式,因为会有一些非平凡的函数依赖,其左侧不是超级键。任何像这样的表本质上都会有两个实体集,每个实体集都有一些属性。基本上,它将有一个左实体集和一个右实体集。左实体集将具有一些唯一标识每个左实体的属性,而右实体集将具有一些唯一标识每个右实体的属性。那些将涉及功能依赖。但是,它们每个都不是候选键,因为您必须将它们组合起来才能获得整个表的候选键。因此,它们不会是超级键,并且会违反 Boyce-Codd 范式。所以 BCNF 会阻止它变冷。任何低于此值的情况都只会捕获某些情况。真的,如果你只记得一种范式,它应该是 BCNF。
无范式消除了多对多关系。每当表中有一个复合键或至少两个非键属性时,它们之间就存在多对多关系。
我认为您要问的是哪种范式消除了传递依赖(不依赖于整个键的属性)。答案是 Boyce-Codd 范式 (BCNF)。如果所讨论的表只有一个键,则 3NF 就足够了,但 BCNF 是一般情况。2NF 本身并不能消除传递依赖。
归档时间: |
|
查看次数: |
3691 次 |
最近记录: |