mysql创建唯一索引最常踩的坑是语法顺序错误、对象名不匹配、在有重复值的列上强行添加、忽略null可重复特性及未区分约束与索引本质差异。

CREATE UNIQUE INDEX 语法写错会直接报错
MySQL 创建唯一索引最常踩的坑是语法顺序或对象名不匹配,比如把表名写成不存在的、字段名拼错、或者在已有重复值的列上强行加索引——这时 MySQL 不会默默忽略,而是立刻抛出 ERROR 1062 或 ERROR 1557。
- 必须确保目标列当前没有重复值,否则
CREATE UNIQUE INDEX会失败;可先用SELECT COUNT(*) FROM table GROUP BY column HAVING COUNT(*) > 1检查 - 语法中索引名不能省略(部分旧版本甚至不允许用反引号包裹索引名),推荐写法:
CREATE UNIQUE INDEX idx_user_email ON users(email); - 如果表已存在大量数据,加唯一索引会锁表(尤其 MyISAM)或阻塞 DML(InnoDB 在 5.6+ 支持在线 DDL,但需显式加
ALGORITHM=INPLACE)
ALTER TABLE ADD UNIQUE 和 CREATE INDEX 效果一样但行为不同
两者最终都生成一个唯一约束 + 唯一索引,但底层机制有差异:前者本质是添加约束(UNIQUE KEY),后者只是建索引。这会影响后续操作和元数据表现。
-
ALTER TABLE users ADD UNIQUE(email);会在information_schema.KEY_COLUMN_USAGE中标记为 CONSTRAINT,而CREATE UNIQUE INDEX不会 - 删除时也不同:删约束得用
DROP INDEX ... ON ...或ALTER TABLE ... DROP INDEX ...;但如果用ADD UNIQUE创建,删的时候用ALTER TABLE ... DROP KEY ...更准确(KEY 名默认和列名一致,除非显式指定) - 如果该列还要作为外键被引用,必须通过约束方式(即
ADD UNIQUE)创建,否则外键定义可能失败
唯一索引对 INSERT/UPDATE 的影响比普通索引更严格
唯一索引不只是加速查询,它强制执行数据层面的排他性校验,这个校验发生在语句执行期,且不可绕过(除非临时禁用唯一检查,但极不推荐)。
- 插入重复值时,MySQL 返回
ERROR 1062: Duplicate entry 'xxx' for key 'idx_name',注意错误信息里明确写了哪个索引触发的 - 批量插入(
INSERT IGNORE或INSERT ... ON DUPLICATE KEY UPDATE)能缓解冲突,但前提是冲突字段正好命中唯一索引的列组合 - 联合唯一索引(如
(user_id, category))中,只要两个值组合相同就拒绝,单个字段重复没关系;这点容易被误判为“没生效” - NULL 值在唯一索引中被视为互不相等(即允许多行 NULL),这是标准 SQL 行为,但和业务直觉可能冲突,需要提前确认设计意图
唯一索引不是主键,别指望它自动 NOT NULL
很多人以为加了唯一索引就等于“这个字段不能空”,其实完全不是一回事。唯一索引本身不改变字段是否允许 NULL,而主键自带 NOT NULL 约束。
- 执行
CREATE UNIQUE INDEX idx_phone ON users(phone);后,phone字段仍可插入NULL,且允许多条NULL - 如果业务上要求“非空且唯一”,必须额外加
ALTER TABLE users MODIFY phone VARCHAR(20) NOT NULL;,否则索引无法覆盖空值场景 - 想一步到位,应该用约束语法:
ALTER TABLE users ADD CONSTRAINT uk_phone UNIQUE (phone);,再配合MODIFY设为 NOT NULL,二者缺一不可











