2011-08-18 44 views
2

如果表中存在对称关系,如何以优雅的方式表示它? 例如,有一个表Friend,其中应包含两个用户的用户标识。如果我们在这个表中使用UID1UID2,当我们要找出是否A_uid和B_uid是朋友,我们应该使用如何表示数据库建模中的对称关系

SELECT * FROM Friend WHERE (UID1 = A_uid AND UID2 = B_uid) OR (UID1 = B_uid AND UID2 = A_uid); 

因为UID1UID2是表示友好一样。 而在这个困境中最重要的是UID1UID2是对称的。

我觉得这很丑,想知道是否有更好的方法来处理它。

谢谢!

回答

4

一个想法从我的头顶:如果你的UID类型都受到了全序,你可以做这样的事情:

CREATE TABLE friends (
    uid1 uid REFERENCES users, 
    uid2 uid REFERENCES users, 
    PRIMARY KEY (uid1, uid2), 
    CONSTRAINT uid1_above_uid2 CHECK(uid1 < uid2) 
); 

然后你的查询将不得不把较低的一个在第一。但是,你可以保护与保证一个存储过程,你这样做:

CREATE FUNCTION friends_with(uid, uid) RETURNS SETOF friends AS $$ 
    SELECT * FROM friends WHERE uid1 = LESSER($1, $2) AND uid2 = GREATER($1, $2) 
$$ LANGUAGE SQL; 

这当然会被翻译成您所选择的RDBMS。

现在你的查询是这样的:

SELECT * FROM friends_with(5001, 2393); 
SELECT * FROM friends_with(2393, 5001); 

,他们返回相同的结果。另一方面,你可以用程序来保护它,而不会把约束条件放在那里,我只是认为它可以方便地防止你不止一次地插入相同的关系。