直接加 unique 会因表中存在重复值而失败,需先查重清理;null 值不触发冲突;未显式命名则约束名难追踪。报错 duplicate entry 时,应执行 select col, count() from t group by col having count() > 1 查重,清理后用 alter table t add constraint uk_col unique (col) 添加显式命名约束。

直接加 UNIQUE 不一定能防住重复——如果表里已有重复值,ALTER TABLE ... ADD UNIQUE 会立刻失败;如果字段允许 NULL,多个 NULL 也不触发冲突;没显式命名约束,后续删起来得查 information_schema 才能知道名字。
ALTER TABLE 加唯一约束时提示 Duplicate entry 怎么办
MySQL 在添加约束前会全表扫描校验,只要存在两行值相同(比如 email = 'a@b.com'),就会中断并报错:Duplicate entry 'a@b.com' for key 'uk_email'。
- 先查重复项:
SELECT email, COUNT(*) FROM users GROUP BY email HAVING COUNT(*) > 1 - 根据业务决定清理方式:删掉冗余行(如保留
MIN(id)对应的记录)、用UPDATE统一值、或导出后人工去重 - 确认无重复后再执行:
ALTER TABLE users ADD CONSTRAINT uk_email UNIQUE (email) -
ALTER IGNORE TABLE已在 MySQL 5.7.4+ 被移除,别试
单字段 vs 多字段唯一约束的写法差异
单字段加约束容易写错括号和关键字位置;多字段必须用联合语法,不是叠加多个单列约束。
- 正确单字段写法:
ALTER TABLE users ADD UNIQUE KEY uk_phone (phone)(带显式名 + 字段在括号内) - 错误写法:
ALTER TABLE users ADD UNIQUE (phone)(匿名约束,名字难追踪);ALTER TABLE users ADD UNIQUE KEY phone (phone)(约束名和列名同名,易混淆);ALTER TABLE users ADD UNIQUE KEY (phone)(缺约束名,MySQL 5.7+ 报ERROR 1064) - 联合唯一必须写成:
ALTER TABLE student_course ADD CONSTRAINT uk_stu_course UNIQUE (student_id, course_id),不是UNIQUE(student_id), UNIQUE(course_id) - 联合约束中任一字段为
NULL,整行不参与去重判断 ——(1, NULL)和(1, NULL)是允许的
建表时就加唯一约束,为什么还要显式命名
CREATE TABLE 时不命名,MySQL 会自动生成约束名(比如 users_email),但这个名字在跨库迁移、复制表、或多人协作时极易冲突,导致 ERROR 1022: Can't write; duplicate key in table。
- 建表时推荐写法:
CREATE TABLE users (id INT PRIMARY KEY, email VARCHAR(255), CONSTRAINT uk_user_email UNIQUE (email)) - 不写约束名的列级写法:
email VARCHAR(255) UNIQUE,MySQL 仍会生成默认名(通常为列名),只是语法上省略了CONSTRAINT关键字 - 如果业务要求“非空且唯一”,必须额外加
NOT NULL:email VARCHAR(255) NOT NULL UNIQUE,否则NULL值会被无视
最常被忽略的是:唯一约束本质是创建唯一索引,它不阻止 NULL,也不校验逻辑空值(比如空字符串 '' 和 ' ' 被视为不同值);真正要防重复,得结合业务清洗 + 约束 + 应用层兜底,不能只靠一条 ADD UNIQUE。











