添加主键前必须确保字段非空且唯一,否则alter table会失败;需先检查并清理null值和重复数据,再执行add primary key;联合主键按字段顺序影响索引效率;变更主键须先drop再add,并注意外键和自增属性处理。

MySQL 添加主键前必须确保字段非空且唯一
直接对已有表加主键,ALTER TABLE 会失败,除非目标列已满足主键约束:不能有 NULL 值、不能有重复值。常见报错是 ERROR 1171 (42000): All parts of a PRIMARY KEY must be NOT NULL 或 ERROR 1062 (23000): Duplicate entry。
实操建议:
- 先检查目标列是否含
NULL:SELECT COUNT(*) FROM table_name WHERE column_name IS NULL; - 再查重复值:
SELECT column_name, COUNT(*) FROM table_name GROUP BY column_name HAVING COUNT(*) > 1; - 若存在
NULL或重复,需先清理(如用UPDATE填充默认值、DELETE冗余行或加WHERE条件过滤) - 清理后,再执行
ALTER TABLE ... MODIFY COLUMN ... NOT NULL显式设为非空(即使原定义没写NOT NULL,主键也强制要求)
单列主键:用 ADD PRIMARY KEY 最简方式
当字段已非空且唯一,添加单列主键最常用语法是 ADD PRIMARY KEY,它会自动基于该列创建聚集索引(InnoDB 下)。
示例(给 users 表的 id 列加主键):
ALTER TABLE users ADD PRIMARY KEY (id);
注意点:
- 如果表原本已有主键,这条语句会报错
ERROR 1068 (42000): Multiple primary key defined,需先DROP PRIMARY KEY - 不指定索引名时,MySQL 自动生成名为
PRIMARY的约束 - 执行后可通过
SHOW CREATE TABLE users;验证
多列联合主键:括号内按顺序写多个字段
联合主键适用于业务上由多个字段共同唯一标识一行的场景(如订单明细表的 order_id + product_id)。
语法和单列一致,只是括号里写多个列名,用逗号分隔:
ALTER TABLE order_items ADD PRIMARY KEY (order_id, product_id);
关键细节:
- 字段顺序影响索引结构和查询效率——
WHERE order_id = ?能用上索引,但仅WHERE product_id = ?不能 - 联合主键下,
(1,2)和(2,1)是不同组合,各自唯一 - 一旦设了联合主键,单独对其中任一列执行
ADD PRIMARY KEY会失败(因主键已存在)
主键已存在时,不能直接 ADD,得先 DROP 再 ADD
MySQL 不支持 ALTER TABLE ... MODIFY PRIMARY KEY 这类“修改主键”语法。想换主键列,必须显式删旧建新。
例如把主键从 id 换成 uuid:
ALTER TABLE users DROP PRIMARY KEY; ALTER TABLE users ADD PRIMARY KEY (uuid);
风险提示:
-
DROP PRIMARY KEY在 InnoDB 中会重建整张表(尤其大数据量时耗时明显) - 若原主键是自增列(
id INT AUTO_INCREMENT),DROP PRIMARY KEY后AUTO_INCREMENT属性不会自动消失,但后续插入可能出错,建议连同MODIFY一起重置 - 外键依赖该主键的子表,需先删外键约束,否则
DROP PRIMARY KEY会失败
NULL 或隐式类型转换导致的重复判断上。










