我有一个包含两列的数据库;电子邮件地址和标志设置的枚举列。我希望能够在一列(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 。
所以当table
。member_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.
答案 0 :(得分:1)
我知道问这个问题已经有2年了,但是为了其他人也有类似的挑战,需要回答。在不得不查看更多评论和中提琴之前,我几乎没有回答就回答了这个问题! @tadman条评论。
我需要类似的实现,但用例却不同,@tadman注释是我一直在寻找的确切解决方案。这是他针对您的问题的详细解决方案:
注意::在下面的步骤中,我假设表
截断表以清除所有数据RegisteredMembers
已经存在,并且没有冲突的数据。如果存在冲突的数据,则可能必须 通过执行TRUNCATE RegisteredMembers
步骤1:使用两列RegisteredMembers
和member_status
在email_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对此问题发表评论