mysql添加唯一约束必须显式命名且字段括号紧贴unique key后,如alter table users add unique key uk_email (email);未命名会自动生成难维护名,有重复数据或null处理不当均导致失败。

ALTER TABLE ADD UNIQUE KEY 语法必须带约束名和括号位置
直接执行 ALTER TABLE users ADD UNIQUE (email) 虽能成功,但 MySQL 会自动生成类似 users_email_uk 的约束名,后续删约束时得先查 SHOW CREATE TABLE users 才能知道真实名字;更稳妥的做法是显式命名:ALTER TABLE users ADD UNIQUE KEY uk_email (email)。注意字段列表 (email) 必须紧贴 UNIQUE KEY uk_email 后面,不能写成 ADD UNIQUE KEY (email)(MySQL 5.7+ 报 ERROR 1064),也不能写成 ADD UNIQUE KEY email (email)(若表中已有 email 列,此处会被解析为列名而非约束名,语义混乱)。
已有重复数据时 ADD UNIQUE KEY 会直接失败
唯一约束底层依赖唯一索引,而索引要求值全局唯一。只要表里存在两行 email = 'test@example.com',命令就会中断并报错:ERROR 1062 (23000): Duplicate entry 'test@example.com' for key 'uk_email'。必须先清理:
- 用
SELECT email, COUNT(*) FROM users GROUP BY email HAVING COUNT(*) > 1;找出所有重复值 - 根据业务决定:删多余行、合并记录,或加条件过滤(注意:普通
UNIQUE KEY不支持WHERE,如需“仅对 active 用户去重”,得用生成列 + 函数索引) -
ALTER IGNORE TABLE在 MySQL 5.7.4+ 已被移除,强行使用会报错,不可依赖
NULL 值在 UNIQUE 下不冲突,但容易误判业务意图
MySQL 允许任意数量的 NULL 值共存于唯一约束字段中——这是 SQL 标准行为,不是 bug。但如果你本意是“每个用户必须填邮箱且不能重复”,只加 UNIQUE 是不够的:
- 先确保非空:
ALTER TABLE users MODIFY email VARCHAR(255) NOT NULL; - 再加约束:
ALTER TABLE users ADD UNIQUE KEY uk_email (email) - 联合唯一同理:
ADD UNIQUE KEY uk_user_role (user_id, role)中,只要任一字段为NULL,整行就不参与去重判断
删唯一约束别混用 DROP INDEX
很多人以为 UNIQUE KEY 就是唯一索引,所以习惯性写 DROP INDEX uk_email ON users。这在多数情况下可行,但有例外:
- 如果该约束是主键(
PRIMARY KEY),DROP INDEX会失败,必须用ALTER TABLE users DROP PRIMARY KEY - 如果约束由建表时隐式定义(如
email VARCHAR(255) UNIQUE),它没有独立约束名,DROP INDEX可能删错或报错 - 最稳妥方式是查清约束名:
SHOW CREATE TABLE users,再用ALTER TABLE users DROP INDEX uk_email或ALTER TABLE users DROP CONSTRAINT uk_email(后者仅在 MySQL 8.0.19+ 支持)











