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

Emm*_*lay 5 sql database database-design

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

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

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

Fra*_*Niu 8

1.对于一对一的关系:

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

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

UserInfo(#UserID);
UserCredential(#UserID)
    FOREIGN KEY (UserID) REFERENCES UserInfo(UserID);
Run Code Online (Sandbox Code Playgroud)

带有前缀"#"的列是表的主键.

2.对于多对一关系:

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

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

Department(#DepartmentID);
Employee(#EmployeeID, DepartmentID)
    FOREIGN KEY (DepartmentID) REFERENCES Department(DepartmentID);
Run Code Online (Sandbox Code Playgroud)

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

CREATE INDEX IX_Employee_DepartmentID ON Employee(DepartmentID);
Run Code Online (Sandbox Code Playgroud)

3.对于多对多关系:

例如表用户和自己.用户可以与另一个用户成为朋友,友谊是双向的(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);
Run Code Online (Sandbox Code Playgroud)

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

表Friendship禁止记录的检查约束如下:

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

表中的检查约束仅禁止像(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);
Run Code Online (Sandbox Code Playgroud)


Alb*_*nbo 5

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

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