传递依赖有什么问题?

时间:2012-03-30 21:02:22

标签: sql database database-design transitive-dependency

我的数据库设计中有一些传递依赖项。我的上司告诉我,这些可能会导致错误。我发现很难找到资源,告诉我这些依赖项将如何导致错误。他们会引起什么样的问题?

我不是在争论这个事实,只是渴望了解它们可能导致什么样的问题。

编辑以获取更多详细信息:

来自维基百科:

传递依赖性 传递依赖是间接函数依赖,其中X→Z仅凭X→Y和Y→Z。

5 个答案:

答案 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(即传递依赖)

现在出现问题:

  1. 如果您同时删除了FrenchEnglish课程,那么您也会删除他们的教师John Doe,他的电话号码将永远丢失。
  2. 除非您先为他添加Instructor,否则无法向数据库中添加新的Course,或者您可以复制Instructors table中的数据,这更糟糕。
  3. 如果教练John Doe更改了他的电话号码,那么您将需要更新他教授的所有课程,这些课程很容易出错。
  4. 您不能从数据库中删除教师,除非您删除他教授的所有课程或将其所有字段设置为空。
  5. 如果您决定保留教练的出生日期怎么办?您必须在Birth Date表中添加Courses字段。这听起来合乎逻辑吗?为什么首先在课程表中保留教师信息。

答案 1 :(得分:10)

表达3NF的一种方法是:

所有属性都应该取决于密钥,整个密钥以及密钥。

传递依赖性X-> Y-> Z违反了该原则,导致数据冗余和潜在的修改异常。


让我们打破这个:

  1. By definition功能依赖关系X-> Y-> Z也传递,X <-Y必须坚持。
  2. 如果Y是键,则X <-Y将保持,因此Y不能成为键。 (FOOTNOTE1)
  3. 由于Y不是键,因此任何给定的Y都可以在多行中重复。
  4. Y-> Z表示持有相同Y的所有行也必须保持相同的Z. (FOOTNOTE2)
  5. 在多行中重复相同的(Y,Z)元组不会向系统提供任何有用的信息。它是多余的
  6. 简而言之,由于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/