“友谊”数据库中的唯一对

时间:2010-08-29 23:53:44

标签: sql relationship

我发布此问题,这有点是我的其他question的摘要。

我有两个数据库
1)db_users。
2)db_friends。

我强调它们存储在不同服务器上的单独数据库中,因此无法使用外键。

在'db_friends'中,我有'tbl_friends'表,其中包含以下列:
- id_user
- id_friend

现在如何确保此表中的每一对都是唯一的('tbl_friends')?
我想在表级别,而不是通过查询。

例如这些是无效行
1 - 2
2 - 1

我希望这是不可能添加的。

此外 - 我会如何搜索用户713的所有朋友,而他可以被提及,在某些友情行,在第二列('id_friend' )?

4 个答案:

答案 0 :(得分:6)

您可能无法在数据库级别执行此操作 - 您的应用程序代码必须执行此操作。如果你确保你的tbl_friends记录总是输入(lowId,highId),那么典型的PK /唯一索引将解决重复的问题。事实上,我会把你的tbl_friends中的列重命名为(id_low,id_high),以加强这一点。

您使用用户713查找任何内容的查询将类似于

SELECT id_low AS friend FROM tbl_friends WHERE (id_high = ?)
UNION ALL
SELECT id_high AS friend FROM tbl_friends WHERE (id_low = ?)

为了提高效率,你可能想要向前和向后索引 - 即(id_user,id_friend)和(id_friend,id_user)。

如果你必须在数据库级别执行此操作,那么在插入之前将参数交换为(低,高)的存储过程将起作用。

答案 1 :(得分:3)

您必须使用触发器来强制执行该业务规则 使tbl_friends中的两列成为主键(唯一约束失败)只能确保不能存在相同集的重复:1,2只能出现一次,但2,1只能出现。

  

如果可以在第二列('id_friend')的某些友谊行中提及他,我将如何搜索用户713的所有朋友?

您可以使用IN

WHERE 713 IN (id_user, id_friend)

..或UNION:

JOIN (SELECT id_user AS user
        FROM TBL_FRIENDS
      UNION ALL
      SELECT id_friend
        FROM TBL_FRIENDS) x ON x.user = u.user

答案 2 :(得分:1)

嗯,对这对列的唯一约束会让你到达一半。我认为确保您没有得到反转版本的最简单方法是添加一个约束,确保id_user< id_friend。您需要在插入时补偿此排序,但它将为您提供所需的数据库级别约束,而无需复制数据或依赖外键。

关于第二个问题,要找到id = 1的所有朋友,你可以从tbl_friend中选择id_user,id_friend,其中id_user = 1或id_friend = 1,然后在你的客户端代码中抛出所有1,而不管列。

答案 3 :(得分:0)

你可以做到的一种方法是将两个朋友分成两行:

CREATE TABLE FriendPairs (
  pair_id INT NOT NULL,
  friend_id INT NOT NULL,
  PRIMARY KEY (pair_id, friend_id)
);

INSERT INTO FriendPairs (pair_id, friend_id)
VALUES (1234, 317), (1234, 713);

请参阅?插入它们的顺序无关紧要,因为两个朋友都进入了friend_id列。因此,您可以轻松地强制执行唯一性。

您还可以轻松查询713的朋友:

SELECT f2.friend_id
FROM FriendPairs AS f1
JOIN FriendPairs AS f2 ON (f1.pair_id = f2.pair_id)
WHERE f1.friend_id = 713