主键必须是整数类型、非空、唯一,且一个表只能有一个;建表时应在create table中直接定义,支持单字段、联合及命名约束,自增需显式声明auto_increment;已有表加主键前须确保数据非空且唯一,严禁用varchar/uuid等低效类型,删除用drop primary key。

主键必须是整数类型、非空、唯一,且一个表只能有一个主键;它不是可选配置,而是数据完整性与查询性能的基础保障。
建表时直接定义主键字段
最稳妥的方式是在 CREATE TABLE 语句里把主键和字段定义写在一起。MySQL 会自动为该字段加 NOT NULL 和唯一索引,省去后续补约束的麻烦。
- 单字段主键:直接在字段后加
PRIMARY KEY,例如id INT PRIMARY KEY - 联合主键:在所有字段定义完后用
PRIMARY KEY (col1, col2)显式声明 - 带名字的主键约束(便于后期管理):
CONSTRAINT pk_user_id PRIMARY KEY (id) - 如果同时要自增,必须写成
id INT PRIMARY KEY AUTO_INCREMENT,不能拆开或漏掉AUTO_INCREMENT
给已有表添加主键
用 ALTER TABLE ... ADD PRIMARY KEY 是常见操作,但容易失败——关键在于目标字段是否满足主键前提条件。
- 字段值必须全部非空(
NOT NULL),否则报错ERROR 1171: All parts of a PRIMARY KEY must be NOT NULL - 字段值必须唯一,重复值会导致
ERROR 1062: Duplicate entry - 推荐先清理数据:
UPDATE t SET id = NULL WHERE id = 0→DELETE FROM t WHERE id IS NULL→ 再执行ALTER TABLE t ADD PRIMARY KEY (id) - 不要用
MODIFY或CHANGE直接加PRIMARY KEY,它不检查数据一致性,可能静默失败
主键字段类型与常见踩坑点
主键不是“设了就行”,类型选错或隐式转换会让后续插入、JOIN、分库分表全崩。
- 严禁用
VARCHAR、UUID、TEXT做主键字段——即使语法通过,也会因索引效率低、排序不稳定引发线上慢查 -
INT和BIGINT的选择要看业务量:INT UNSIGNED最大到 42.9 亿,超量会溢出变成 0 或报错ERROR 167: Out of range value - Navicat 界面勾选“主键”只是 UI 操作,真正生效靠 SQL 定义;导出建表语句时务必确认含
PRIMARY KEY关键字 - 删除主键用
ALTER TABLE t DROP PRIMARY KEY即可,不需要指定字段名
真正难的不是语法,而是判断哪个字段该当主键、它的生命周期是否可控、以及上下游系统是否依赖这个值做关联或缓存——这些没法靠 ADD PRIMARY KEY 一行命令解决。











