【发布时间】:2018-02-12 17:34:39
【问题描述】:
我有一个包含两列的数据库;电子邮件地址和用于标志设置的枚举列。我希望能够在一列(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?
我知道这里的一些更了解 DB 的人会问 “你疯了吗?你为什么要使用 ENUM?” 我只能说我们使用 ENUM 作为从一个(非常!)旧的 Y/N 标志系统到一个在同一列中有更多选项的系统(从而最大限度地减少前端 PHP 列引用更新的大量注释)。
我/我们可以轻松地将member_status ENUM 列重建为一个 int 值,以引用另一个表,例如 状态表;但是同样的查询又回来了:
我想根据另一列的值将一列索引为唯一仅。
所以当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.
- 我可以用 ENUM 做到这一点吗?
- 如果不能,我可以使用其他列类型来执行此操作吗?
- 如果以上任何一项都为“是”,我该怎么做?
【问题讨论】:
-
唯一约束通常不能是有条件的。我会问为什么在某些情况下允许重复很重要,但在其他情况下不允许重复。
-
不应允许已验证的成员使用重复的电子邮件地址。未经验证的成员没关系。
-
如果没关系,无论如何都阻止重复地址。
-
您可以设置复合
UNIQUE索引,但我不确定这是否是您想要的。请记住,唯一约束中的 NULL 值将被忽略,因此如果您的辅助组件为 NULL,则允许您重复。您可能可以在email_addr, verified上建立索引,如果verified为NULL,您可以拥有无限的记录,但只有一个设置为verified=1。 -
这听起来像我想要的;出于某种原因,我确实在一个列上想到了
NULL,但是……不,没关系,我用一个新列(布尔值)对其进行了测试,并且有效。感谢您的逻辑演练