5

我有一个带有主键 _id 的用户的 MySQL 表,我想将友谊(在其他用户的朋友列表上的可见性)表示为带有 userId 外键对的表。我在想类似的事情:

CREATE TABLE UserFriendships (
  userIdA INT NOT NULL,
  userIdB INT NOT NULL,
  PRIMARY KEY (userIdA, userIdB),
  FOREIGN KEY (userIdA) REFERENCES Users(_id)
  FOREIGN KEY (userIdB) REFERENCES Users(_id)
)

据我了解,这将允许(userIdA = 2, userIdB = 7)(userIdA = 7, userIdB = 2)作为不同的行插入。我想要每个友谊一行,也就是说每对 userIds 一行。

有谁知道我可以如何改善这一点?即使满足上述约束条件,要获取用户 foo 的所有朋友的列表,我也必须进行联合,例如:SELECT userIdB AS friendUserId WHERE userIdA = foo UNION SELECT userIdA WHERE userIdB = foo。这是完成该查询的最佳方式,还是我应该考虑更改我的架构?

4

1 回答 1

5

您可以使用 aTRIGGER BEFORE INSERT来执行业务规则:

  • userIdA始终是具有较低 IDuserIdB的用户,始终是具有较高 ID 的用户

这样, (A,B) 和 (B,A) 的组合都会导致具有相同主键的相同列顺序。

DELIMITER |
CREATE TRIGGER enforce_friendship_id_order BEFORE INSERT ON UserFriendships
  FOR EACH ROW BEGIN
    SET @lowerId := IF(NEW.userIdA < NEW.userIdB, NEW.userIdA, NEW.userIdB);
    SET @higherId := IF(NEW.userIdA > NEW.userIdB, NEW.userIdA, NEW.userIdB);
    SET NEW.userIdA = @lowerId;
    SET NEW.userIdB = @higherId;
  END;
|
DELIMITER ;
于 2013-03-31T18:29:19.803 回答