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

Mic*_*uel 6 mysql mariadb unique-constraint mariadb-10.2

我创建了下表,称为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;
Run Code Online (Sandbox Code Playgroud)

我创建了另一个名为 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;
Run Code Online (Sandbox Code Playgroud)

以前的工作按预期进行,但我需要强制 MySQL 只允许compare表中值的唯一组合。

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

id_1 | id_2
------------
  1  |  2
Run Code Online (Sandbox Code Playgroud)

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

id_1 | id_2
------------
  2  |  1
Run Code Online (Sandbox Code Playgroud)

所以我希望 MySQL 只允许一个1,22,1两个都不允许。

我正在使用 10.2.14-MariaDB - MariaDB 服务器

ype*_*eᵀᴹ 9

由于您使用 MariaDB 10.2,您可以添加一个CHECK约束,强制第一个 id 小于第二个 ( id_1 < id_2)。在 10.2.1 版中添加了CHECK约束

这有一个限制,即您必须以INSERT正确的顺序为语句提供 id ((3,2)即使(2,3)不存在,您也无法插入组合):

ALTER TABLE compare
  ADD CONSTRAINT ids_unique_combination_chk
    CHECK (id_1 < id_2) ;
Run Code Online (Sandbox Code Playgroud)

dbfiddle.uk测试。


如果您不想麻烦您的INSERT语句和过程,您可以使用两个VIRTUAL(或PERSISTENT)列和一个UNIQUE约束。

自 5.2 版以来,MariaDB 中提供了虚拟列,并且在 10.2.1 中取消了一些限制:

ALTER TABLE compare
  ADD small_id BIGINT AS (LEAST(id_1, id_2)) VIRTUAL,
  ADD big_id   BIGINT AS (GREATEST(id_1, id_2)) VIRTUAL,
  ADD CONSTRAINT ids_unique_combination_uq
    UNIQUE (small_id, big_id);
Run Code Online (Sandbox Code Playgroud)

也在 dbfiddle.uk 上测试过:fiddle-2