我的数据库设计中有一些传递依赖项。我的上司告诉我,这些可能会导致错误。我发现很难找到资源,告诉我这些依赖项将如何导致错误。他们会引起什么样的问题?
我不是在争论这个事实,只是渴望了解它们可能导致什么样的问题。
编辑以获取更多详细信息:
来自维基百科:
传递依赖性 传递依赖是间接函数依赖,其中X→Z仅凭X→Y和Y→Z。
答案 0 :(得分:50)
我将通过一个例子来解释:
-------------------------------------------------------------------
| Course | Field | Instructor | Instructor Phone |
-------------------------------------------------------------------
| English | Languages | John Doe | 0123456789 |
| French | Languages | John Doe | 0123456789 |
| Drawing | Art | Alan Smith | 9856321158 |
| PHP | Programming | Camella Ford | 2225558887 |
| C++ | Programming | Camella Ford | 2225558887 |
-------------------------------------------------------------------
Course
,则可以轻松获得Instructor
Course ->Instructor
。Instructor
,则无法获得Course
,因为他可能会教授不同的课程。Instructor
,则可以轻松获得Phone
Instructor->Phone
。这意味着,如果你有一个Course
,那么你可以获得Instructor Phone
,这意味着Course ->Instructor Phone
(即传递依赖)
现在出现问题:
French
和English
课程,那么您也会删除他们的教师John Doe
,他的电话号码将永远丢失。Instructor
,否则无法向数据库中添加新的Course
,或者您可以复制Instructors table
中的数据,这更糟糕。 John Doe
更改了他的电话号码,那么您将需要更新他教授的所有课程,这些课程很容易出错。Birth Date
表中添加Courses
字段。这听起来合乎逻辑吗?为什么首先在课程表中保留教师信息。答案 1 :(得分:10)
表达3NF的一种方法是:
所有属性都应该取决于密钥,整个密钥以及密钥。
传递依赖性X-> Y-> Z违反了该原则,导致数据冗余和潜在的修改异常。
让我们打破这个:
简而言之,由于Y不是键,而Y-> Z,我们违反了3NF。
冗余会导致修改异常(例如,更新某些但不是所有的Zs“连接”到同一个Y基本上会破坏数据,因为您不再知道哪个副本是正确的)。这通常通过将原始表拆分为两个表来解决,一个包含{X,Y},另一个包含{Y,Z},这样,Y可以是第二个表中的键,Z不会重复。< / p>
另一方面,如果X <-Y确实保持(即X-> Y-> Z不可传递),那么我们可以保留单个表,其中X和Y都是键。在这种情况下,Z不会不必要地重复。
(FOOTNOTE1)键是一组(最小)属性,用于在功能上确定关系中的所有属性。基本原理:如果K是一个键,则不能有多个具有相同K值的行,因此任何给定的K值始终与每个其他属性的一个值相关联(假设为1NF)。根据定义(参见FOOTNOTE2),“与一个相关联”与“处于功能依赖”是相同的。
(FOOTNOTE2)By definition,Y-&gt; Z当且仅当每个Y值恰好与一个Z值相关联时。
示例:强>
假设每封邮件只有一位作者,而且每位作者只有一封主电子邮件,那么尝试在同一张表中表示邮件和用户会导致重复发送电子邮件:
MESSAGE USER EMAIL
------- ---- -----
Hello. Jon jon@gmail.com
Hi, how are you? Rob rob@gmail.com
Doing fine, thanks for asking. Jon jon@gmail.com
(实际上,这些都是MESSAGE_ID
s,但让我们在这里保持简单。)
现在,如果Jon决定将他的电子邮件更改为“jon2@gmail.com”,会发生什么?我们需要更新Jon的行两个。如果我们只更新一个,那么我们有以下情况......
MESSAGE USER EMAIL
------- ---- -----
Hello. Jon jon2@gmail.com
Hi, how are you? Rob rob@gmail.com
Doing fine, thanks for asking. Jon jon@gmail.com
......我们不再知道Jon的哪一封电子邮件是正确的。我们基本上丢失了数据!
情况特别糟糕,因为没有声明性约束我们可以用来强制DBMS为我们强制执行这两个更新。客户端代码 会出现错误,可能是在不太考虑并发环境中可能发生的复杂交互的情况下编写的。
但是,如果你拆分表......
MESSAGE USER
------- ----
Hello. Jon
Hi, how are you? Rob
Doing fine, thanks for asking. Jon
USER EMAIL
---- -----
Jon jon@gmail.com
Rob rob@gmail.com
...现在只有一行知道Jon的电子邮件,所以模棱两可是不可能的。
顺便说一下,所有这些都可以被视为DRY principle的另一种表达方式。
答案 2 :(得分:5)
如果你的表中存在传递依赖,那么它就不符合3NF;因此表中存在冗余数据的可能性很高。检查this以澄清这一概念。
答案 3 :(得分:3)
看一下这个链接:
http://en.wikipedia.org/wiki/Transitive_dependency
使用这个例子,如果我在一行更新Jules Verne的国籍而不是另一行,会发生什么?作者国籍仅由作者决定,而不是书籍和作者的组合。因此,通过示例数据结构,我可能会向数据库询问Jules Verne的国籍。如果我运行以下SQL命令
SELECT TOP 1 author_nationality FROM books 作者='Jules Verne'
我可以根据数据库选择TOP 1的方式得到不同的答案。
答案 4 :(得分:1)
我刚刚发表了一篇文章,阐述了为什么传递依赖通常是一个坏主意:http://www.essentialsql.com/get-ready-to-learn-sql-11-database-third-normal-form-explained-in-simple-english/