这是一个多对多的关系,这是一个关系表是必需的。
create table Person (
person_id int not null primary key,
username varchar(100) not null,
... other_cols ...
)
create table Buddy (
person_id1 int not null,
person_id2 int not null,
primary key (person_id1, person_id2),
foreign key (person_id1) reference Person (person_id),
foreign key (person_id2) reference Person (person_id)
)
所以 Person 表显然会为每个 Person 包含 1 行。它将包含有关伙伴的任何数据,因为这会使其非规范化。相反,好友表将包含人员之间的关系。
所以假设你在 Person 表中有这样的东西:
person_id username
1 George
2 Henry
3 Jody
4 Cara
亨利和卡拉是好朋友,乔治和卡拉也是:
person_id1 person_id2
2 4
1 4
如果您需要它以使关系不是隐式相互的,那么您将需要添加额外的行以使其明确。所以现在让我们说亨利认为卡拉是朋友,卡拉同样认为亨利是朋友,而乔治认为卡拉是朋友,但卡拉不回应乔治:
person_id1 person_id2
2 4
4 2
1 4
缺少的 4 1 表明 Cara 不认为 George 是好友。这使事情变得非常干净并避免了数据异常。您可以调整关系而无需处理 Person 数据。您还可以在外键上定义删除级联规则,以便删除 Person 会自动为您删除所有关联关系。相反,您可能希望阻止这种情况,在这种情况下,您可以在外键上指定限制(默认值),以防止删除仍定义关系的 Person。
查询也很简单:
Cara 有多少好友(假设好友列表的关系是隐含的):
select count(*) from Person
join Buddy on person_id = person_id1 or person_id = person_id2
where name = 'Cara'
对于不暗示关系的情况,最好改为重命名列,如下所示:
person_id considers_as_buddy_id
2 4
4 2
1 4
4 3
select count(*) from Person P
join Buddy B on P.person_id = B.person_id
where name = 'Cara'
这将返回 Cara 将多少人视为好友。在这种情况下 2. 虽然 Jody 不认为 Cara 是好友 - 所以要找出相互关系,您可以这样做:
select count(*) from Person P
join Buddy B on P.person_id = B.person_id and
B.considers_as_buddy_id = P.person_id
where name = 'Cara'