Идея из головы в голову: если ваши типы 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;
Это, конечно, должно быть переведено в выбранную вами СУБД.
Теперь ваши запросы выглядят такэто:
SELECT * FROM friends_with(5001, 2393);
SELECT * FROM friends_with(2393, 5001);
и они возвращают одинаковые результаты.
С другой стороны, вы можете защитить его с помощью процедур, не накладывая ограничения CHECK
, я просто думаю, что это удобночтобы вы не могли случайно вставить одно и то же отношение более одного раза.