如何在数据库建模中表示对称关系

时间:2011-08-18 05:22:59

标签: database symmetry

如果表中存在对称关系,如何以优雅的方式表示它? 例如,有一个名为Friend的表,其中应包含两个用户的用户ID。如果我们在此表中使用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是对称的。

我认为这很难看,想知道是否有更好的方法。

谢谢!

1 个答案:

答案 0 :(得分:5)

我的头脑中的一个想法:如果你的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);

他们会返回相同的结果。

另一方面,您可以使用过程保护它而不会在其上设置CHECK约束,我只是认为防止您不小心插入同一个关系会很方便。