27

我的数据库包含一个用户表。每个活跃用户都有一个唯一的用户名。我希望能够停用用户并释放他们正在使用的用户名,但将它们保留在同一个表中。

有没有办法只有条件地强制执行唯一性约束?

4

5 回答 5

65

添加另一个名为isactive. 在 上创建唯一约束(username, isactive)

然后,您可以同时拥有活动和非活动用户名。您将无法拥有两个活动用户名。

如果您想要多个非活动名称,请使用NULL的值isactiveNULL值可以在唯一索引中重复。

于 2013-08-17T22:13:47.717 回答
9

不,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 约束将防止插入具有重复用户名的新行。

于 2013-08-17T21:43:50.580 回答
2

不同的方式达到相同的结果。对于所提出的问题,可能并不真正需要。但仅供参考。

  1. 在插入/更新时创建触发器
  2. 检查是否存在具有当前(新)记录值的重复记录。
    一个。这可以通过计算重复项或检查是否存在具有相同值但主键不同的其他记录来检查
  3. 如果找到引发信号以引发错误

如果您的条件复杂而无法确定唯一性,则此方法最适合。还要考虑性能成本。

样本

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 ;
于 2017-10-12T12:35:41.500 回答
1

我将创建另一个名为 FORMER_NAME 的(非唯一)字段,并在用户处于非活动状态时将原始名称移动到该字段。不需要不可能的特殊唯一性约束。

于 2021-01-05T20:27:08.213 回答
0

不,如果有唯一索引(因此得名),则不能有重复项。添加额外的列以使每条记录唯一。或更改值使其唯一。

不推荐,但例如您可以添加时间戳“USER DELETED 2013/08/17:233805”

于 2013-08-17T21:39:13.783 回答