SQL表中两个条目之间的关联

时间:2010-10-14 09:40:26

标签: sql database database-design

想象一下,您有一个存储人员列表的数据库表。你想在人与人之间建立一种关系,即我与人J的朋友。

我想在这种情况下,需要第二个表来存储人员关联。该表包含两个字段(person1,person2),每个条目对应两个人之间的一对一关系。

这是对的还是有更聪明的方法呢?此方法使关联表像n_users ^ 2一样缩放。

3 个答案:

答案 0 :(得分:7)

1。对于一对一的关系:

e.g。表UserInfo(用于用户的个人信息)和表UserCredential(用于用户的登录信息)。这是表分割,以减少一条记录的大小。

为每个表指定相同的主键,并从一个(辅助表)到另一个(主表)创建外键:

UserInfo(#UserID);
UserCredential(#UserID)
    FOREIGN KEY (UserID) REFERENCES UserInfo(UserID);

带有前缀“#”的列是表的主键。

2。对于多对一关系:

e.g。表员工和表部门。每个员工只属于一个部门,但部门可能有零到多个员工。

将表Department的主键列添加到Employee表中,并从Emp到Dep创建一个FK:

Department(#DepartmentID);
Employee(#EmployeeID, DepartmentID)
    FOREIGN KEY (DepartmentID) REFERENCES Department(DepartmentID);

如果您经常需要使用Employee.DepartmentID列进行查询,则可以在其上创建索引:

CREATE INDEX IX_Employee_DepartmentID ON Employee(DepartmentID);

3。对于多对多关系:

e.g。表用户和自己。用户可以与另一个用户成为朋友,友谊是双向的(A是B的朋友,所以B也是A的朋友)。并且用户可以跟随另一个用户,但以下是单向的(A跟随B但B可能不跟随A同时)。在图论中,友谊是一个无向图,后面是有向图。

需要单独的表来表示多对多关系:

User(#UserID);
Friendship(#LeftUserID, #RightUserID)
    FOREIGN KEY (LeftUserID) REFERENCES User(UserID)
    FOREIGN KEY (RightUserID) REFERENCES User(UserID)
    CHECK (LeftUserID < RightUserID);
Following(#LeftUserID, #RightUserID)
    FOREIGN KEY (LeftUserID) REFERENCES User(UserID)
    FOREIGN KEY (RightUserID) REFERENCES User(UserID)
    CHECK (LeftUserID <> RightUserID);

表Friendship和Following都使用组合主键(有两列或更多列)。

表Friendship中的check-constraint禁止记录,如:

  • (A,A):一个人不应该是自己的朋友。
  • (B,A):对于A和B之间的友谊,记录(A,B)就足够了。这是 DRY 原则的一个案例。

表格中的check-constraint仅限于禁止(A,A)等记录。 (A,B)表示A跟随B,(B,A)表示B跟随A,这两个记录具有不同的含义,因此它们都是必要的。

您可以使用第二列创建其他索引来优化查询(假设PK是聚簇索引):

CREATE UNIQUE INDEX IX_Friendship_Right_Left
    ON Friendship(RightUserID, LeftUserID);
CREATE UNIQUE INDEX IX_Following_Right_Left
    ON Following(RightUserID, LeftUserID);

答案 1 :(得分:5)

是的,如果您想建立多对多关系,这是正确的。这就是所有人都可以有很多朋友。

如果你有一对多的关系,就像所有人都有一个老板(或没有老板)你不需要额外的表,那么你只需要在人员表中有一个BossId列。

答案 2 :(得分:0)

您可能还想建立关联类型。在这种情况下,您最好使用2个表,RelationshipTypes和Relationships。唯一键可以在所有3个关系字段中。

Relationships
  PersonId
  RelatedPersonId
  RelationshipTypeId

RelationsShipTypes
  Id
  Name