【问题标题】:Should there be a foreign key "to" an associative entity, or "from" the associative entity?是否应该有“到”关联实体或“来自”关联实体的外键?
【发布时间】:2018-11-26 21:19:07
【问题描述】:

我正在尝试为书店建立一个数据库。以下是整体设计的一个较小的子集。

目前我有一个带有 ISBN(主键)、标题和其他一些属性的 Book 实体。

我有一个 Author 实体,其名称为 author_id(主键)。

因为书和作者是多对多的关系。我有以 ISBN 和 author_id 作为属性的 Authorted_title 关联实体。所以 ISBN 是 Book 实体的外键,author_id 是 Author 实体的外键。

我的问题是,是否可以将 Book 实体中的 ISBN 作为外键,将 Author 实体中的 author_id 作为外键到关联实体 Authored_title 中的各个属性,而不是相反(与我之前提到的相反段)?

我想了想之后有点困惑。就 FK 而言,表之间是否存在“to”和“from”之类的东西?

【问题讨论】:

    标签: sql database erd


    【解决方案1】:

    外键约束的想法是,如果表 Y 中没有与 X 相关的记录,它会阻止在表 X 中创建记录。在您的情况下, Author 和 Book 具有主键,并且 Book_Author 表将 M:M 关系分解为两个 1:M 关系以 Author 和 Book 为键;在您首先在 Book 中创建记录并在 Author 中创建记录之前,您无法在 Book_Author 中创建记录

    您似乎在询问是否可以反过来执行此操作,并将 Book 表和 Author 表键入 Book_Author 表

    答案是否定的(嗯,没有什么是不,但这是一个非常非常不应该)

    为了接受外键关系,Book_Author 必须有一个主键。你会选择什么作为主键?您可以使用 BookID+AuthorID。您可以有一个单独的递增 int 或一个 guid,但是将这种 PK 放在分解 M:M 关联的表上是“仅仅因为你可以,并不意味着你应该”的列表。 您不能只为主键的一部分建立外键,因此如果 Book 和 Author 将作为 Book_Author 的键,而 Book_Author 将有一个复合 PK,那么其他表(Book、Author)将需要额外的列来覆盖密钥的其他元素;你最终会在 book 表中存储一个作者,在 author 表中存储一本书。那么一本有两位作者的书呢?它需要 Book 表中的两个条目,每个作者一个。我们应该在规范化数据库时主动删除这种软数据重复。这一步是主动去规范化。在 Book_Author 表上放置一个递增的 PK 存在相同的论点;您如何表示一本书有 2 个作者?您的关联表中需要 2 行,它们不能有相同的 PK 值,所以让我们给它们不同的值:

    BookAuthorId, Book, Author
    1, GoodOmens, NeilGaiman
    2, GoodOmens, TerryPratchett
    

    现在我们必须为这些图书创建引用我们在 Book_Author 中的主键列的图书:

    Book Name, BookAuthorId, Description
    Good Omens, 1, A funny story about life as a fallen angel
    Good Omens, 2, A funny story about life as a fallen angel
    

    你花更多的时间去思考“Book_Author 应该是主键,Book 和 Author 表应该是它的外键”这个概念,你就会越多地意识到它绝对不可行并且什么都解决不了,它只会创建头痛

    一本书,书表中的一行。一位作者,作者中的一行。我们有这些规则是因为只有一个 Terry Pratchett,一个 Neil Gaiman,一个叫做 Good Omens 的故事。所有这些“一个”东西都应该有一行,一个主键标识它。当我们想将这些东西组合在一起时,我们使用另一个具有复合键的表,以确保我们不能将 Neil Gaiman 记录为两次写好预兆,以及确保我们链接在一起的书和作者确实存在的外键。将书分配给不存在的作者,将不存在的书分配给作者是没有意义的..

    所以,这就是为什么这些东西是“那样”圆的; “反过来”没有好处

    【讨论】:

      【解决方案2】:

      没有。您的初始实现是正确的。链接表中的 FK 引用实体表中的 PK。

      编辑

      无法添加引用链接表的外键,因为外键需要引用主键。您需要链接表上的两列都是主键,显然这是不可能的。

      FK -> PK 关系本质上是many -> one。在您的情况下,链接表上的许多行将引用实体表上的单行。

      【讨论】:

      • 好的,但我想知道第二种方法是否合法。如果有,有什么区别?
      猜你喜欢
      • 2012-05-31
      • 1970-01-01
      • 1970-01-01
      • 2017-02-02
      • 2016-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多