仅允许复合主键的唯一值组合

时间:2018-04-24 10:11:45

标签: mysql sql database

我创建了名为books的下表:

CREATE TABLE IF NOT EXISTS `books` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` TEXT NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

我创建了另一个名为compare的平板电脑来比较books表中的任意两本书:

CREATE TABLE IF NOT EXISTS `compare` (
`id_1` BIGINT UNSIGNED NOT NULL,
`id_2` BIGINT UNSIGNED NOT NULL,
PRIMARY KEY (`id_1`,`id_2`),
FOREIGN KEY (`id_1`) REFERENCES books(`id`),
FOREIGN KEY (`id_2`) REFERENCES books(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

之前的工作符合预期,但我需要强制MYSQL仅允许compare表中唯一的值组合。

例如,如果我在compare表中有以下行:

id_1 | id_2
------------
  1  |  2

我想强制MYSQL不允许我插入以下行:

id_1 | id_2
------------
 2  |  1

所以我希望MYSQL只允许1,22,1

2 个答案:

答案 0 :(得分:2)

另一种方法是交换插入前触发器中的值以确保id_1< ID_2:

    CREATE TRIGGER `compare_before_insert` BEFORE INSERT ON `compare` FOR EACH ROW 
    BEGIN
      DECLARE t BIGINT;
        IF(NEW.id_1 > NEW.id_2) THEN
            SET t = NEW.id_1;
            SET NEW.id_1 = NEW.id_2;
            SET NEW.id_2 = t;        
        END IF;
    END

这将允许您使用该键使这些对唯一。

答案 1 :(得分:1)

在MySQL中(至少在版本8之前),如果希望数据库强制执行约束,则需要使用触发器执行此操作。

delimiter $$

create trigger compare_insert_trigger before insert on compare
for each row
begin
    if (exists (select 1
                from compare c
                where c.id2 = new.id1 and c.id1 = new.id2
               )
       ) then
        signal sqlsate '45000'
        set message_text = 'Book pair already exists in compare';
    end if;
end;$$

delimiter ;

当然,您仍然需要唯一约束。