1

这个问题是基于线程的

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

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

替代文字 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

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

4

7 回答 7

4

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

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

并且因为许多问题可能使用相同的标签。

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


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

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


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

StackOverflow 的简单模型

这生成了以下 ER 图:

ER图

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

于 2009-07-26T21:42:19.250 回答
4

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

于 2009-07-26T21:44:46.280 回答
1

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

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

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

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

于 2009-07-26T21:45:52.097 回答
1

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

于 2009-07-26T21:46:03.830 回答
1

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

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

它的原因与关系数据库模型有关

于 2009-07-26T21:56:17.553 回答
1

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

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

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

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
于 2009-07-26T22:03:29.817 回答
0

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

于 2009-07-26T21:47:53.857 回答