ALTER TABLE 添加主键约束时为什么报错 Duplicate entry
主键约束要求字段值非空且唯一,如果表中已有重复值或 NULL 值,
ALTER TABLE ... ADD PRIMARY KEY会直接失败,错误信息类似
Duplicate entry '' for key 'PRIMARY'或
Cannot add or update a child row: a foreign key constraint fails。 先检查目标字段是否有 NULL 或重复值:
SELECT col, COUNT(*) FROM table_name GROUP BY col HAVING COUNT(*) > 1 OR col IS NULL;清理数据后再执行,例如用
UPDATE填充 NULL、用
DELETE去重,或添加
NOT NULL后再设主键 若字段是自增 ID,建议先
ALTER TABLE table_name MODIFY id INT AUTO_INCREMENT;再加主键,避免隐式类型不匹配
外键约束添加失败的三个常见原因
MySQL 中外键(
FOREIGN KEY)依赖存储引擎(仅 InnoDB 支持)、字段类型严格一致、以及被引用列必须有索引。任意一项不满足都会报错,典型如
ERROR 1215 (HY000): Cannot add foreign key constraint。 确认两张表都是
ENGINE=InnoDB:用
SHOW CREATE TABLE parent_table;查看,不是则先
ALTER TABLE table_name ENGINE=InnoDB;检查字段类型是否完全一致:比如
INT和
INT UNSIGNED不兼容,
VARCHAR(20)和
VARCHAR(25)也不行;字符集和排序规则(collation)也需相同 确保被引用列(通常是父表的主键或唯一索引列)已建索引:若没有,先执行
ALTER TABLE parent_table ADD INDEX (ref_col);
用 ALTER TABLE 添加 CHECK 约束要注意版本
MySQL 8.0.16+ 才支持原生
CHECK约束,低版本(如 5.7)虽然能解析语法但会忽略,不报错也不生效。如果你在 5.7 执行
ALTER TABLE t ADD CHECK (age >= 0);,语句成功,但约束实际不存在。 验证是否生效:查
information_schema.CHECK_CONSTRAINTS表(8.0+),或用
SHOW CREATE TABLE t;看输出里是否包含
CHECK子句 低版本替代方案:靠应用层校验,或用触发器(
BEFORE INSERT/UPDATE)模拟,但性能开销大、逻辑分散 注意:CHECK 表达式不能含子查询、存储函数、参数化变量,也不能引用其它列的别名
UNIQUE 和 NOT NULL 约束可以合并添加但不能混用语法
添加唯一约束和非空约束是两个独立操作,MySQL 不支持像
ADD UNIQUE NOT NULL这样的复合语法。误写会导致语法错误
ERROR 1064。 正确顺序:先
ALTER TABLE t MODIFY col VARCHAR(50) NOT NULL;(改列属性),再
ALTER TABLE t ADD UNIQUE (col);(加索引级约束) 如果该列已有数据且含 NULL,
MODIFY ... NOT NULL会失败,必须先处理 NULL 值 UNIQUE 约束本身允许一个 NULL(标准行为),但若想彻底禁用 NULL,必须显式加
NOT NULL,否则仍可能存入空值干扰业务逻辑 约束不是“加完就万事大吉”。外键的级联动作(
ON DELETE CASCADE)、CHECK 的表达式求值时机(INSERT 时还是 UPDATE 时)、甚至字符集变更都可能让已有约束失效或行为突变——上线前务必在同版本环境完整验证。
