为什么我不应该为多个关系使用一张桌子?


12

假设我的数据库中有多个关系,例如商店,员工和销售,并且我想用简单的二进制关系连接对。我个人将创建一个名为Employee_Store和Employee_Sale的表,并使用由外键组成的自然键。

现在,我的同事坚持要为多个关系创建一张表。对于上面的示例,可能有一个名为EmployeeLinks的表:

EmployeeLinks(
    IdLink int PK, 
    IdEmployee int FK null,
    IdStore int FK null,
    IdSale int FK null,
    LinkType int not null
)

请以充分的理由帮助我,为什么这不是一个好主意。我有自己的论点,但我想让他们保密,并听听您的公正意见。

编辑:

最初,上表没有主键(!)。因为外键允许为null,所以替代键是唯一的选择。


3
这就像OTLT或EAV,但更糟糕的是,它会扩散列而不是行!
一天,2012年

Answers:


13

您的同事提议什么作为此链接表的主键?
主键列当然不能为NULL:上表具有可为空的值。

上面的示例中没有任何自然的行标识符(即PK是什么)(IDENTITY列不是主键),因此在任何建模过程中都会失败。甚至不要考虑创建没有某​​种模型(ERD,ORM,IDEF1X等)的表

您还需要CHECK约束,以确保您没有3向链接。

最后,由于错误的原因,您正在进入第4和第5范式区域。

我在互联网上找不到任何示例:这表明这是多么愚蠢


4
+1I can't find any examples on the internet: that shows how stupid this is
JNK 2012年

我对主键更清楚了。而且,显然我的同事实际上在
大约

@Tomasz Pluskiewicz:代理密钥不是主密钥!选择它是为了在执行时补充自然键。请参见dba.stackexchange.com/a/13779/630。此外,您的同事还应向我们展示有关该技术的权威文章。我见过的时候堆满了垃圾,但我不再重复了……
gbn 2012年

12

我能想到的第一个实际原因是性能。

在“传统”模型中,您可以在Idemployee, Idstore任何字段上都有唯一的索引,并在查询中获得出色的性能。插入件的维护也很容易。独特的索引使您更频繁地合并联接,这可以使很多工作变得非常JOIN快。

在示例模型中,要获得良好的性能,您将需要在表中的每个FK字段上至少具有一个字段索引,理想情况下,在所有要引用的组合上都应具有覆盖索引,即:

  • 员工/店铺
  • 员工/销售

我不确定什么是链接类型,但是如果您引用它,则应该将其编入索引。

无论是否填充该字段,都将需要为表中的每一行维护这些索引。您可以添加一个过滤器,但是使用如此多的组合也会变得棘手。

这也会使您的逻辑复杂化。 您要么需要在employeeid上进行查找,找到存储值为空的行,然后进行更新;或者,仅为每个新链接插入新行,这会破坏合并字段的目的。

基本上,您将使用更多的磁盘空间,需要维护更多的索引,并且基本上没有理由使逻辑复杂化。唯一的“好处”是要处理的表更少。


LinkType列是一个区分符。只需告诉一行实际相关的对。如果您问我的话,只会增加一些麻烦。
Tomasz Pluskiewicz 2012年

@TomaszPluskiewicz我认为向他展示为什么糟糕的最好方法是建立一个同时包含两种表的样本数据集并运行一些查询。他的模型会比传统模式慢得多
JNK

4

如果这些关系具有相同的属性,并且/或者如果您要汇总多个关系中的数据,则将多个关系放入一个表中将很有用。

如果关系类型是由用户在运行时定义的,则很有必要。但是,实际情况很少如此。

在您的示例中,关系不共享属性,关系甚至引用了两个不同的表。这使得难以实施约束,并且设计也不太直观。

如果创建表确实要花钱,我只会选择该设计。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.