如何避免 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)))
这允许该对以任一顺序排列,但仍然只有一次。
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)))
这允许该对以任一顺序排列,但仍然只有一次。