在多列列的唯一索引上使用ENUM

时间:2018-02-12 17:34:40

标签: mysql enums

我有一个包含两列的数据库;电子邮件地址和标志设置的枚举列。我希望能够在一列(email_addr)上添加唯一索引,但仅测量ENUM列是否为值V(索引1)。

CREATE TABLE `RegisteredMembers` (
 `reg_id` int(8) NOT NULL AUTO_INCREMENT,
 `mem_name` varchar(70) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'Surname',
 `mobile` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
 `email_addr` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL,
 `member_status` enum('V','B','A','P') COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'A' 
          COMMENT 'Validated, Blocked, Anonymous, Pending',

 UNIQUE KEY `unique_RegMemId` (`Reg_id`),
 KEY `EmailAddr` (`email_addr`) USING BTREE
) 

ENGINE=MyISAM AUTO_INCREMENT=2292 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

因此,例如member_status = 'P'行可以包含重复的email_addr值,但member_status = 'V'行不能重复发送email_addr值。

我已尝试在PhpMyAdmin上进行上述操作,但由于当前数据重复(非V ENUM值),它会返回各种一致性错误或失败。

read some posts似乎非常广泛地展示了this can't be done,但也this might可能?{/ p>

我知道一些比较清楚的DB人会问"你疯了吗?为什么你要使用ENUM?" 我只能说我们使用ENUM作为从(非常!)旧的Y / N标志系统过渡到同一列中有更多选项的系统(从而最大限度地减少了前端的大量PHP列引用更新。)

我/我们可以轻松地重建member_status ENUM列作为 int 值,引用另一个表,例如状态表;但后来又回来了同样的问题:

我想根据另一列的值将一列列为唯一 ONLY

所以当tablemember_status ==' V'那么email_addr必须是唯一的。

将索引列组合为一个唯一列并不像table那样工作。member_status ==' P'然后可以允许email_addr列的重复。

示例:

`reg_id`  |  `member_status`  |   `email_addr`
----------------------------------------------------------------
    1     |          P        |  me@homere.com
    2     |          A        |  horse@shoes.com        
    3     |          V        |  martin@koolaide.co.uk
    4     |          A        |  me@homere.com           // this is ok.       
    5     |          A        |  horse@shoes.com         // this is ok too
    6     |          B        |  failed@life.org
    7     |          V        |  martin@koolaide.co.uk   // this is invalid. 
  • 我可以使用ENUM执行此操作吗?
  • 如果不能,我可以使用其他列类型吗?
  • 如果上述任何一种情况都是"是"?
  • ,我该怎么做呢?

1 个答案:

答案 0 :(得分:1)

我知道问这个问题已经有2年了,但是为了其他人也有类似的挑战,需要回答。在不得不查看更多评论和中提琴之前,我几乎没有回答就回答了这个问题! @tadman条评论。

我需要类似的实现,但用例却不同,@tadman注释是我一直在寻找的确切解决方案。这是他针对您的问题的详细解决方案:

注意::在下面的步骤中,我假设表RegisteredMembers已经存在,并且没有冲突的数据。如果存在冲突的数据,则可能必须 通过执行TRUNCATE RegisteredMembers

截断表以清除所有数据

步骤1:使用两列RegisteredMembersmember_statusemail_addr表上创建复合唯一键

ALTER TABLE `RegisteredMembers` ADD UNIQUE KEY `member_status_is_email_addr` (`member_status`,`email_addr`);

步骤2:修改member_status列以使其可为空,并将其限制为仅'V'枚举值,因为任何其他枚举值都将假定为null以允许其他插入相同的{{1} }值

email_addr

第3步:这就是您的架构所需的全部修改。仅在经过验证的情况下,将ALTER TABLE `RegisteredMembers` CHANGE `member_status` `member_status` ENUM('V') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL; 插入“ B”,“ A”以及“ P”和“ V”位置。

我已经有一个工作类似的实现。如果您对此还有其他疑问,请发表评论,我会尽快答复。

信用:@tadman对此问题发表评论