Как представить отношения симметрии в моделировании базы данных - PullRequest
4 голосов
/ 18 августа 2011

Если в таблице есть отношение симметрии, как изобразить его элегантно?Например, есть таблица с именем Friend, в которой должен содержаться идентификатор пользователя двух пользователей.Если мы используем UID1 и UID2 в этой таблице, когда мы хотим выяснить, являются ли A_uid и B_uid друзьями, мы должны использовать

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

, поскольку UID1 и UID2 одинаковыв представлении дружбы. И самое важное в этой дилемме состоит в том, что UID1 и UID2 являются симметричными.

Я думаю, что это уродливо, и я хочу знать, есть ли лучший способ сделать это.

Спасибо!

1 Ответ

5 голосов
/ 18 августа 2011

Идея из головы в голову: если ваши типы 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, я просто думаю, что это удобночтобы вы не могли случайно вставить одно и то же отношение более одного раза.

...