在mysql中,只有当值为false时才可以有唯一约束吗?
例如,我想在Name
上使用唯一约束,但仅限于Archived = false
。
换句话说,我有一个字段archived
,我将其用作软删除,如果我将唯一的constraitn放在Name周围并存档,则删除两个具有相同名称的内容将导致违规。因此想知道数据库是否可以处理这种类型的唯一约束
答案 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;