繁体   English   中英

多对多关系设计 - 交叉表设计

[英]Many to Many Relation Design - Intersection Table Design

我想知道对于多对多关系的交叉表有什么更好的设计。

我正在考虑的两种方法是:

CREATE TABLE SomeIntersection 
(
     IntersectionId UNIQUEIDENTIFIER PRIMARY KEY,
     TableAId UNIQUEIDENTIFIER REFERENCES TableA NOT NULL,
     TableBId UNIQUEIDENTIFIER REFERENCES TableB NOT NULL,
     CONSTRAINT IX_Intersection UNIQUE(TableAId, TableBId )
) 

要么

CREATE TABLE SomeIntersection 
(
     TableAId UNIQUEIDENTIFIER REFERENCES TableA NOT NULL,
     TableBId UNIQUEIDENTIFIER REFERENCES TableB NOT NULL,
     PRIMARY KEY(TableAId, TableBId )
) 

一个人对另一个人有好处吗?
编辑2:****请注意:我计划使用Entity Framework为数据库提供API。 考虑到这一点,一个解决方案在EF中的效果是否优于另一个?

编辑:在相关的说明中,对于两列引用同一个表的交集表(下面的示例),是否有办法使两个字段在记录上不同?

CREATE TABLE SomeIntersection 
(
     ParentRecord INT REFERENCES TableA NOT NULL,
     ChildRecord INT REFERENCES TableA NOT NULL,
     PRIMARY KEY(TableAId, TableBId )
)

我想阻止以下情况

ParentRecord          ChildRecord
=================================
      1                    1         --Cyclical reference! 

这是一个争论的话题。 我更喜欢第一种形式,因为我认为能够通过单个值查找映射行更好,并且喜欢强制执行一个可能 - 愚蠢的一致性,即在每个表中都可以使用单列主键。 其他人则认为拥有该专栏是对空间的愚蠢浪费。

我们每隔几个月在新泽西州的一家酒吧见面几轮裸肩拳击。

如果您的“交集”实际上是一个实体,则使用版本1 ,这意味着:

  • 它有其他属性
  • 你可以搜索那些对象(而不是导航关系)

用户版本-2,如果它是纯粹的NM关系表。 在这种情况下还要确保:

  • 你有PK(CLUSTERED)与你的搜索表相关的第一列更频繁:例如,如果你的表是人员地址,那么我会假设你会更频繁地搜索所有人的地址然后为所有人在这个地址。 所以你应该先把你的PK包含在PersonID中
  • 你仍然可以有另一个单列UNIQUE标识符,但只是:

    1. 或者不要把它变成PK
    2. 或者使它成为PK,但指定NON CLUSTERED,以便您可以使用CLUSTERED作为覆盖两个引用列的UNIQUE索引
    3. 除非您的设计使用GUID,否则您可以坚持使用INT IDENTITY列类型

在这两种情况下,您可能想要创建另一个覆盖2列的INDEX,但是在另一个顺序中,如果您经常从关系的另一侧进行搜索。

第二个版本对我来说是最好的,它避免了创建额外的索引。

你正在建设的是一个“交叉点”。

我对我在学校的数据库教授有一个非常清楚的记忆,说交叉关系几乎总是一个实体本身,所以通常值得为它分配空间。 这表明前者更“正确”。

也就是说,我个人倾向于选择后者。 这实际上取决于您是否将直接检索其中一个记录,或者您是否只在连接其中一个原始表时使用该表。

如果你选择第一个,只需在PK上使用IDENTITY,就不需要浪费空间(磁盘和内存缓存)和UNIQUEIDENTIFIER。

从开发人员的角度来看,我更喜欢前者。 在处理它时更容易编写和测试。

我不需要检查两个键来检索唯一记录。

如果交集表中没有任何其他字段,它实际上不需要自己的ID,添加一个不会增加任何好处。 但是,如果您要将其他字段放入该表中,并且在许多情况下,您将使用自己的ID作为主键。

当然,经验法则,但你去了。

回答你的第二个问题......

您只需要添加一个检查约束,如下所示:

CREATE TABLE SomeIntersection 
(
     ParentRecord INT REFERENCES TableA NOT NULL,
     ChildRecord INT REFERENCES TableA NOT NULL,
     PRIMARY KEY(TableAId, TableBId),
     CHECK (ParentRecord <> ChildRecord)
)

第一个的好处:

能够通过单个值查找连接表。 这使得一些查找操作在客户端更简单。

一些ORM(NHibernate)还需要每个实体中的id才能使持久性正常工作。

第二个的好处:

更简单的数据模型,无需创建其他索引。

需要的内存更少。

第二个更好。 它将接线盒(交叉盒)限制为不具有同一对的多个外观。 如果接线盒中没有其他列,则无论如何都不会查找此表,除非通过两个外键。

鉴于TableAId-TableBId组合是唯一的,并且该表仅用于实现多对多关系,我将使用第二个选项。 从纯逻辑的角度来看,第一个实现减少到第二个。 从结构的角度来看,您的数据库需要维护主键/索引以及第一个实现的约束,而第二个只需要维护主键/索引。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM