我可以有条件地执行唯一性约束吗?

时间:2013-08-17 21:35:47

标签: mysql unique-constraint

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

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

5 个答案:

答案 0 :(得分:43)

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

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

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

答案 1 :(得分:8)

不,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' boolean,您就可以检查此列并返回user_deleted常量来代替username列:

SELECT IF(u.user_deleted,'USER DELETED',u.username) AS username

(使用值1表示逻辑“用户删除”条件。)

此方法的一大优势是不必修改username列,username值和UNIQUE约束将阻止插入具有重复用户名的新行。

答案 2 :(得分:3)

实现相同结果的不同方式。问题可能不是真正的要求。但仅供参考。

  1. 在插入/更新
  2. 上创建触发器
  3. 检查是否找到包含当前(NEW)记录值的重复记录。      
    一个。这可以通过计算重复或检查存在具有相同值但具有不同主键的OTHER记录来检查
  4. 如果发现提出Signal以引发错误
  5. 如果您的条件很复杂,决定唯一性,这是最合适的。还要考虑性能成本。

    <强>示例

    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 ;
    

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

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