2011-08-18 96 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); 

,他們返回相同的結果。另一方面,你可以用程序來保護它,而不會把約束條件放在那裏,我只是認爲它可以方便地防止你不止一次地插入相同的關係。