我发布此问题,这有点是我的其他question的摘要。
我有两个数据库:
1)db_users。
2)db_friends。
我强调它们存储在不同服务器上的单独数据库中,因此无法使用外键。
在'db_friends'中,我有'tbl_friends'表,其中包含以下列:
- id_user
- id_friend
现在如何确保此表中的每一对都是唯一的('tbl_friends')?
我想在表级别,而不是通过查询。
例如这些是无效行:
1 - 2
2 - 1
我希望这是不可能添加的。
此外 - 我会如何搜索用户713的所有朋友,而他可以被提及,在某些友情行,在第二列('id_friend' )?
答案 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