phpMyAdmin创建唯一索引遇Error 1062:数据无重复却报错求助
这种看起来字段内容明明唯一却报重复键的问题,我碰到过好几次,大多是一些容易被忽略的细节在搞鬼,给你列几个排查方向:
排查隐形字符或空格:肉眼看着一样的字符串,说不定藏着前后空格、换行符或者其他不可见的ASCII字符。比如"test"和"test "(末尾多空格),肉眼根本分不出来,但MySQL会判定为不同?不对,哦不,你的情况是报错重复,那可能是两个看起来不同的字符串,实际因为隐形字符导致存储内容一致?直接用十六进制查看真实内容就能揪出问题:执行
SELECT your_column, HEX(your_column) FROM your_table;,对比每条记录的十六进制值,就能发现差异。如果是空格问题,先清理数据:UPDATE your_table SET your_column = TRIM(your_column);注意NULL值的特殊性:InnoDB引擎里,唯一索引会把多个NULL值视为重复项!如果你的字段里有超过一个NULL,加唯一索引肯定会报错。先查一下:
SELECT COUNT(*) FROM your_table WHERE your_column IS NULL;,要是有多个NULL,要么给这些NULL设置一个唯一的默认值,要么用MySQL 8.0+支持的部分唯一索引:CREATE UNIQUE INDEX idx_your_column ON your_table (your_column) WHERE your_column IS NOT NULL;大小写敏感性坑:如果你的字段是VARCHAR这类字符型,数据库排序规则是不区分大小写的(比如常见的utf8_general_ci),那"Apple"和"apple"会被MySQL判定为相同内容。先看表的排序规则:
SHOW CREATE TABLE your_table;,如果确实是不区分大小写的,那检查下有没有大小写不同但实际被视为重复的数据。要是需要区分大小写,要么修改字段的排序规则为utf8_bin,要么在创建索引时指定:CREATE UNIQUE INDEX idx_your_column ON your_table (your_column COLLATE utf8_bin);数据截断导致的重复:比如你的字段定义是VARCHAR(10),但之前插入的数据有超过10个字符的,MySQL会悄悄截断(旧版本可能没警告),导致原本不同的内容变成一样的。你可以检查每条数据的实际长度:
SELECT your_column, LENGTH(your_column) FROM your_table;,对比字段定义的长度,看看有没有被截断的情况。缓存或刷新问题:有时候删了报错数据,但phpMyAdmin的缓存没更新,或者MySQL的表缓存没刷新。试试手动刷新表:
FLUSH TABLE your_table;,或者退出phpMyAdmin重新登录后再执行ALTER语句。检查其他索引或触发器:看看表上有没有其他索引包含这个字段,或者有没有触发器在修改数据时偷偷改动了这个字段的值。用
SHOW INDEX FROM your_table;查看所有索引,SHOW TRIGGERS LIKE 'your_table';查看触发器,排除这些因素的干扰。
内容的提问来源于stack exchange,提问作者Gabe O

