【问题标题】:Why does many-to-many data structure require two additional tables?为什么多对多数据结构需要两个额外的表?
【发布时间】:2009-07-26 21:39:43
【问题描述】:

本题基于the thread

如果我们有一对多的数据结构,我们需要有一个“帮助表”来存储例如一个人的电话号码。许多人不能拥有相同的电话号码。

我期待解释为什么我们在多对多关系之间需要两个“帮助表”。这方面的一个例子是一个问题站点,许多用户可以在其中添加相同的标签:

alt text http://files.getdropbox.com/u/175564/db/db-55.png

为什么我们需要Question-Tag-xrefQuestion-Tags 表?

为什么我们不能只有一个标签表如下?

   Question_id   |    tag
   1                  C 
   1                  C++
   2                  Java
   2                  C

为什么两个不同的问题具有相同的标签对计算机来说是个问题?

【问题讨论】:

    标签: database data-structures many-to-many one-to-many


    【解决方案1】:

    那只是一张“额外”的桌子。

    这是因为同一个问题可能有很多标签。

    而且因为同一个标签可能被许多问题使用。

    您需要在某个地方存储(questionId、tagId)并确保没有重复。


    我没有关注你关于这个主题的问题,但这里的设计似乎有些糟糕。我以为您只有一张额外的桌子,因为我认为您的结构合理。你没有。

    为什么 Question-Tags 既有标签字符串又有标签 id?这对我来说没有多大意义。


    我不想回到问题的顺序。尽管如此,我还是想尝试说明我在说什么。因此,我使用NORMA 工具为 StackOverflow 的这一部分创建了一个非常简单的 Object-Role Modeling 模型:

    这生成了以下 ER 图:

    请注意,我们需要为标签保留“额外”表,因为没有保留有关标签的额外信息。此外,不需要存储作为标签表外键的标签 id,因为标签名称已经是唯一的。如果我们保留有关标签的附加数据,那么可能会有一个单独的标签表,主键仍然是标签名称。如果它成为性能问题,可以将其更改为使用整数 id,在这种情况下,标签名称仍将获得唯一索引。

    【讨论】:

    • 那么实际的“字符串”标签是否存储在表Question-tags中?
    • 我试图通过重命名变量来解决这个问题。请看看同样的问题是否仍然存在。
    • @Masi:这些不是我画的。 NORMA 工具根据我创建的对象角色建模模型绘制了 ER 图。它还创建了创建表和约束所必需的 SQL Server 语句,并且会为 DB2、Oracle、MySQL、Postgres、XML Schema 甚至 LINQ to SQL 类做同样的事情。它会生成一堆带有.php扩展名的文件,但是由于我不懂PHP,所以我不能说它们是什么。
    • 其实这不是我的符号。这是对象角色建模表示法。看看ormfoundation.org 网站。括号中的内容是参考模式。虚线表示它是一个值类型,而不是表示实体类型的实线。空的矩形是角色。角色上的点表示它是强制性的。角色或角色序列上的条形表示唯一性。这一切都使该工具能够用语言表达关系:
    • 示例:用户提出的问题。对于每个问题,只有一个用户提出了该问题。可能同一用户提出了多个问题。
    【解决方案2】:

    这是normalization的问题。恕我直言,关于这个主题的最好的书之一是Joe Celko's SQL for Smarties。基本上,您可以避免所谓的“异常”。在您的示例中,如果我删除所有带有“Java”标签的问题,我将永远无法知道我曾经有一个名为“Java”的标签(删除异常)。破解表格也很重要,因为您需要外部参照表来描述主体之间关系的属性。

    【讨论】:

    • 假设您有一个非常大的站点,应该易于扩展,例如与 Google MapReduce 相关的内容。我不明白为什么你应该删除依赖项。依赖可以减少接口的数量和表的数量,保证效率和可扩展性。为什么你不能有非常依赖的结构,类似于 Git 的工具会警告异常?备份会告诉你出了什么问题。
    【解决方案3】:

    http://en.wikipedia.org/wiki/Database_normalization

    这对计算机来说不是问题,但是 RDBMS 理论说,db 应该通过规范化减少信息重复。 下面是 Codd 博士所说的关于标准化的必要性:

    1. 将关系集合从不需要的插入、更新和删除依赖项中解放出来;
    2. 随着新类型数据的引入,减少重新构建关系集合的需要,从而延长应用程序的生命周期;
    3. 使关系模型为用户提供更多信息;
    4. 使关系集合对查询统计信息保持中立,因为这些统计信息可能会随着时间的推移而发生变化。

    E.F. Codd,“数据库关系模型的进一步规范化”

    【讨论】:

      【解决方案4】:

      问题是您希望表结构的标准化程度之一。通常,您不希望将信息存储在多个位置。为此,当许多项目的数据可能重复时,您可以对其进行规范化——将该数据移动到一个单独的表中,另一个表中的多行可以通过存储数据的键而不是数据本身来引用它。当您有许多行共享相同的数据并且您想要对其进行规范化时,您需要一个中间表来存储表之间的关系(引用对)。

      【讨论】:

        【解决方案5】:

        在关系数据库中,多对多关系被实现为两个互惠的一对多关系,每个关系都需要一个额外的表(除了直接表示实体的表之外)来实现。

        • 首先,第一个表中的一行与第二个表中的多行之间存在一对多关系。
        • 第二,第二个表的一行与第一个表的多行之间的另一种一对多关系。

        原因与relational database model有关。

        【讨论】:

          【解决方案6】:

          只是为了补充其他人所说的(我不会重复他们的cmets)

          根据我的经验,它通常不称为帮助表,而是连接表。通常,您要处理的事情比简单的关键字更复杂。 “额外”表模拟了其他 2 个实体之间的关系。

          另一个例子可能是我有一个营销活动,它涉及到许多收件人联系人。这两个实体都不依赖于另一个。任何特定的活动都会有许多联系人,并且任何联系人都可以发送多个活动。在这种情况下,连接表模拟了谁被发送到哪个活动的历史记录。

          Campaign 
           - CampaignID (PK)
           - other columns
          
          Contact 
           - ContactID (PK)
           - other columns
          
          CampaignContact
           - CampaignContactID (PK)
           - CampaignID (FK)
           - ContactID (FK)
          

          这与一对多关系(有时称为主从关系)有很大不同。这里一个典型的例子是 Invoice -> InvoiceItems。发票项目专门链接到一张且只有一张父发票。

          Invoice
           - InvoiceID (PK)
           - other columns
          
          InvoiceItem
           - InvoiceItemID (PK)
           - InvoiceID (FK)
           - other columns
          

          【讨论】:

          • 你怎么能有一个你有一个条目的表? -- 我认为CampaingContact(CampaingID) 是对Campaign(campaignID) 的pk 和fk。 --- 嗯,我看不出我上面的表格中可能只有一个条目(圈出)。应该是类似的情况,数据结构应该是一样的。
          • Campaign、Contact and Invoice 和 InvoiceItem 都是复杂的实体,但为了说明关系省略了细节。
          【解决方案7】:

          通常它不仅仅是一个标签列,它包含更多的信息。因此,如果信息很多,那么您就有冗余数据(在您的示例中您有 2 个“C”值)。然后,如果相同的值存在于多个地方,更新就会成为问题。所以规则是数据应该放在一个地方,它的 ID 在其他地方用来引用它。然后当你更新它时,只需要在一个地方完成。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-01-08
            • 2012-12-29
            • 1970-01-01
            • 2013-06-27
            • 2015-08-24
            • 2022-01-18
            • 2022-10-18
            • 1970-01-01
            相关资源
            最近更新 更多