列值等于false时的唯一约束?

时间:2017-06-29 15:20:23

标签: mysql

在mysql中,只有当值为false时才可以有唯一约束吗?

例如,我想在Name上使用唯一约束,但仅限于Archived = false

换句话说,我有一个字段archived,我将其用作软删除,如果我将唯一的constraitn放在Name周围并存档,则删除两个具有相同名称的内容将导致违规。因此想知道数据库是否可以处理这种类型的唯一约束

1 个答案:

答案 0 :(得分:0)

相关示例

我认为执行此操作的唯一方法是使用触发器和信号。 只需将触发器更新并插入即可。

类似方法的相关示例从这里开始:http://cvuorinen.net/2013/05/validating-data-with-triggers-in-mysql/

DELIMITER $$

CREATE TRIGGER example_before_insert_allow_only_one_active
     BEFORE INSERT ON example_tbl FOR EACH ROW
     BEGIN
          IF NEW.active = 1 AND (SELECT COUNT(id) FROM example_tbl 
               WHERE active=1 AND foreign_key_id=NEW.foreign_key_id) > 0
          THEN
               SIGNAL SQLSTATE '45000'
                    SET MESSAGE_TEXT = 'Cannot add or update row: only one active row allowed per type';
          END IF;
     END;
$$

CREATE TRIGGER example_before_update_allow_only_one_active
     BEFORE UPDATE ON example_tbl  FOR EACH ROW
     BEGIN
          IF NEW.active = 1 AND (SELECT COUNT(id) FROM example_tbl
               WHERE id<>NEW.id AND active=1 AND foreign_key_id=NEW.foreign_key_id) > 0
          THEN
               SIGNAL SQLSTATE '45000'
                    SET MESSAGE_TEXT = 'Cannot add or update row: only one active row allowed per type';
          END IF;
     END;
$$

适用于您的案例

DELIMITER $$

CREATE TRIGGER example_before_insert_allow_only_one_not_archived
     BEFORE INSERT ON example_tbl FOR EACH ROW
     BEGIN
          IF NEW.archived = 0 AND (SELECT COUNT(id) FROM example_tbl 
               WHERE name=NEW.name) > 0
          THEN
               SIGNAL SQLSTATE '45000'
                    SET MESSAGE_TEXT = 'Cannot add or update row: existing name exists and you are entering with archived = 0 (false)';
          END IF;
     END;
$$

CREATE TRIGGER example_before_update_allow_only_one_not_archived
     BEFORE UPDATE ON example_tbl  FOR EACH ROW
     BEGIN
          IF  NEW.archived = 0 AND (SELECT COUNT(id) FROM example_tbl 
               WHERE name=NEW.name) > 0
          THEN
               SIGNAL SQLSTATE '45000'
                    S SET MESSAGE_TEXT = 'Cannot add or update row: existing name exists and you are entering with archived = 0 (false)';
          END IF;
     END;
$$

最后,您可能真的有兴趣在SQL中使用以下语句,如果您只需要一个NAME for archived = false,但是对于archived = true则无限制。

SELECT COUNT(id) FROM example_tbl  WHERE name=NEW.name AND archived = 0;