为 MySQL 创建部分唯一约束

lin*_*nqu 4 mysql null constraint mysql-5.5

我和之前的帖子有同样的问题:PostgreSQL 多列唯一约束和 NULL 值。但是那里的解决方案不适用,因为我使用的是 MySQL 而不是 PostgreSQL。

我的桌子看起来像这样:

CREATE TABLE `my_table` (
  `id` bigint(20) NOT NULL,
  `col1` bigint(20) NOT NULL,
  `col2` bigint(20) NOT NULL,
  `col3` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
)
Run Code Online (Sandbox Code Playgroud)

我想要三列col1col2并且col3是独一无二的。但是一个正常的唯一约束

UNIQUE KEY `unique_constraint` (`col1`,`col2`,`col3`)
Run Code Online (Sandbox Code Playgroud)

仍然允许我插入相同的行,其col3NULL. 我想禁止这样的条目:

1  | 1 | 1 | NULL
2  | 1 | 1 | NULL
Run Code Online (Sandbox Code Playgroud)

我在上面的帖子中提出了在 MySQL 中搜索部分唯一约束,但显然 MySQL 5.5 不支持。

有人可以给我一个提示,如何在 mysql 中最好地解决这个问题,我也希望有一个高性能的解决方案!

感谢 mysql 的新手(来自 PostgreSQL)!

Der*_*ney 6

想到的唯一选择是BEFORE INSERT触发器。在 5.5 中,您可以使用SIGNAL

DELIMITER $$
CREATE TRIGGER bi_foo BEFORE INSERT on foo
FOR EACH ROW
BEGIN
  IF (ISNULL(NEW.col3) AND (SELECT COUNT(*) FROM foo 
     WHERE col1 = NEW.col1 AND col2 = NEW.col2 AND col3 IS NULL) > 0)
  THEN
    SIGNAL SQLSTATE '45000'
     SET MESSAGE_TEXT = 'Cannot insert this item due to unique constraint', 
         MYSQL_ERRNO = 1001;
  END IF;
END$$
DELIMITER ;
Run Code Online (Sandbox Code Playgroud)

[sqlfiddle]

但是在 5.5 之前,你会这样做:

DELIMITER $$
CREATE TRIGGER bi_foo BEFORE INSERT on foo
FOR EACH ROW
BEGIN
  IF (ISNULL(NEW.col3) AND (SELECT COUNT(*) FROM foo 
     WHERE col1 = NEW.col1 AND col2 = NEW.col2 AND col3 IS NULL) > 0)
  THEN
    SET NEW='Error: Cannot insert this item due to unique constraint';
  END IF;
END$$
DELIMITER ;
Run Code Online (Sandbox Code Playgroud)

[sqlfiddle]