mysql – 没有排序的SQL组合主键(任何一个顺序的整数对都必须是唯一的)

我有一个带有主键_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.这是完成该查询的最佳方式,还是应该考虑更改我的架构?

最佳答案
您可以使用TRIGGER BEFORE INSERT来制定业务规则:

> userIdA始终是ID较低的用户,userIdB始终是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.userIdB);
    SET NEW.userIdA = @lowerId;
    SET NEW.userIdB = @higherId;
  END;
|
DELIMITER ;

相关文章

昨天的考试过程中,有个考点的服务器蓝屏重启后发现Mysql启动不了(5.6.45 x32版本,使用innoDB),重装后...
整数类型 标准 SQL 中支持 INTEGER 和 SMALLINT 这两种类型,MySQL 数据库除了支持这两种类型以外,还扩...
一条 SQL 查询语句结构如下: SELECT DISTINCT &lt;select_list&gt; FROM &lt;left_table&...
数据备份 1. 备份数据库 使用 mysqldump 命令可以将数据库中的数据备份成一个文本文件,表的结构和数据...
概述 在实际工作中,在关系数据库(MySQL、PostgreSQL)的单表数据量上亿后,往往会出现查询和分析变慢...
概述 触发器是 MySQL 的数据库对象之一,不需要程序调用或手工启动,而是由事件来触发、激活,从而实现...