我的数据库包含一个用户表。每个活跃用户都有一个唯一的用户名。我希望能够停用用户并释放他们正在使用的用户名,但将它们保留在同一个表中。
有没有办法只有条件地强制执行唯一性约束?
我的数据库包含一个用户表。每个活跃用户都有一个唯一的用户名。我希望能够停用用户并释放他们正在使用的用户名,但将它们保留在同一个表中。
有没有办法只有条件地强制执行唯一性约束?
添加另一个名为isactive
. 在 上创建唯一约束(username, isactive)
。
然后,您可以同时拥有活动和非活动用户名。您将无法拥有两个活动用户名。
如果您想要多个非活动名称,请使用NULL
的值isactive
。 NULL
值可以在唯一索引中重复。
不,UNIQUE 约束不能是“有条件的”。
一种选择是将username
列设置为 NULL。UNIQUE 约束将允许具有 NULL 值的多行。
您可以将其转换为您想要显示的任何字符串。无论是在应用程序中,还是在 SQL 中
SELECT IFNULL(t.username,'USER DELETED') AS username
FROM mytable t
如果您出于历史/存档目的保留这些行,您可能不想更新该username
列。(如果更改username
列的值,则允许后续语句插入与前一个用户名具有相同值的行。)
您可以改为在表中添加一个附加列,以表示“用户已删除”条件。例如:
user_deleted TINYINT(1) UNSIGNED DEFAULT 0 COMMENT 'boolean'
只要设置了布尔值,您就可以检查此列并返回'USER DELETED'
常量来代替用户名列:user_deleted
SELECT IF(u.user_deleted,'USER DELETED',u.username) AS username
(使用值 1 表示逻辑“用户已删除”条件。)
这种方法的最大优点是username
不必修改列、username
值和 UNIQUE 约束将防止插入具有重复用户名的新行。
不同的方式达到相同的结果。对于所提出的问题,可能并不真正需要。但仅供参考。
如果您的条件复杂而无法确定唯一性,则此方法最适合。还要考虑性能成本。
样本
DELIMITER $$
CREATE TRIGGER `my_trigger` BEFORE INSERT/UPDATE
ON `usertable`
FOR EACH ROW BEGIN
IF EXISTS (SELECT 1 FROM usertable WHERE userid <> NEW.userid AND username = NEW.username AND isactive = 1) THEN
SELECT CONCAT(NEW.username, ' exists !') INTO @error_text;
SIGNAL SQLSTATE '45000' SET message_text = @error_text;
END IF;
END$$
DELIMITER ;
我将创建另一个名为 FORMER_NAME 的(非唯一)字段,并在用户处于非活动状态时将原始名称移动到该字段。不需要不可能的特殊唯一性约束。
不,如果有唯一索引(因此得名),则不能有重复项。添加额外的列以使每条记录唯一。或更改值使其唯一。
不推荐,但例如您可以添加时间戳“USER DELETED 2013/08/17:233805”