如何避免 MySQL 复合主键排列?

How to avoid MySQL composite primary key permutations?

CREATE TABLE Friends_Relations(
    buddy_id VARCHAR(255) NOT NULL,
    mate_id VARCHAR(255) NOT NULL,
    PRIMARY KEY (buddy_id, mate_id),
    FOREIGN KEY (buddy_id) REFERENCES Users(id) ON DELETE CASCADE,
    FOREIGN KEY (mate_id) REFERENCES Users(id) ON DELETE CASCADE
);

有这种相互的友谊关系,其中 (friend_A, friend_B) 与 (friend_B, friend_A) 相同。

我试过添加唯一键,但没有用:

ALTER TABLE Friends_Relation ADD UNIQUE KEY (mate_id, buddy_id);

有没有办法避免这些排列?

你可以这样做:

create table friends_relations (
  buddy_id varchar(255) not null,
  mate_id varchar(255) not null,
  constraint uq1 unique (
    (least(buddy_id, mate_id)), (greatest(buddy_id, mate_id))
  ),
  primary key (buddy_id, mate_id)
);

那么如果它不接受对称行:

insert into friends_relations (buddy_id, mate_id) values (456, 123);
insert into friends_relations (buddy_id, mate_id) values (123, 456); -- fails

请参见 db<>fiddle 中的 运行 示例。

还有一个技巧。您还可以做的是强制执行 buddy_id < mate_id。但是,这将限制您插入数据的方式。例如你可以这样做:

CREATE TABLE Friends_Relations (
    buddy_id VARCHAR(255) NOT NULL,
    mate_id VARCHAR(255) NOT NULL,
    PRIMARY KEY (buddy_id, mate_id),
    FOREIGN KEY (buddy_id) REFERENCES Users(id) ON DELETE CASCADE,
    FOREIGN KEY (mate_id) REFERENCES Users(id) ON DELETE CASCADE,
    constraint ck1 CHECK (buddy_id < mate_id) -- added constraint
);

然后,当您插入时:

insert into Friends_Relations (buddy_id, mate_id) values (123, 456); -- succeeds

insert into Friends_Relations (buddy_id, mate_id) values (456, 123); -- fails

from this dba exchange question

ALTER TABLE Friends_Relation ADD UNIQUE KEY 
((least(buddy_id,mate_id)), (greatest(buddy_id,mate_id)))

这允许该对以任一顺序排列,但仍然只有一次。