最稳妥方式是已有表用alter table modify column加自增主键,新建表在create table中显式声明bigint unsigned not null auto_increment primary key;add column易报错且不满足索引要求。

直接说结论:已有表加自增主键,ALTER TABLE ... MODIFY COLUMN 是最稳妥的方式;新建表就直接在 CREATE TABLE 里写死 AUTO_INCREMENT 和 PRIMARY KEY。别用 ADD COLUMN 硬塞,容易踩坑。
已有表添加自增主键必须用 MODIFY COLUMN
很多人试过 ALTER TABLE t ADD COLUMN id INT NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST,结果报错:ERROR 1075 (42000): Incorrect table definition; there can be only one auto-increment column 或更常见的 ERROR 1067 (42000): Invalid default value for 'id' —— 这是因为 MySQL 要求自增列必须是索引的第一列,而 ADD COLUMN 不保证该字段已建索引或满足唯一性约束。
正确做法是先确保字段存在(哪怕值为空),再用 MODIFY COLUMN 升级属性:
- 如果字段
id已存在但没主键:先ALTER TABLE t MODIFY COLUMN id INT NOT NULL,再ALTER TABLE t ADD PRIMARY KEY (id),最后ALTER TABLE t MODIFY COLUMN id INT NOT NULL AUTO_INCREMENT - 如果字段
id已存在且有主键但没自增:直接ALTER TABLE t MODIFY COLUMN id INT NOT NULL AUTO_INCREMENT - 执行前务必确认该列无重复值、无 NULL 值(
NOT NULL是硬要求)
新建表时自增主键写法要带 PRIMARY KEY 显式声明
AUTO_INCREMENT 本身不隐含主键,它只是一种计数器行为。MySQL 强制要求:自增列必须是 PRIMARY KEY 或 UNIQUE KEY 的第一列。所以这句是错的:
CREATE TABLE t (id INT AUTO_INCREMENT);
正确写法必须明确索引关系:
CREATE TABLE t ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(32) );
或者分开写:
CREATE TABLE t ( id INT NOT NULL AUTO_INCREMENT, name VARCHAR(32), PRIMARY KEY (id) );
注意:NOT NULL 不能省——即使你加了 PRIMARY KEY,MySQL 也不会自动补 NOT NULL 属性,漏写会报错。
自增起始值和重置不是靠 INSERT 控制的
常见误解:“插入一条 INSERT INTO t (id) VALUES (100) 就能让下一条从 101 开始”——这确实能生效,但它是“副作用”,不是规范操作。真正可控、可预期的方式只有:
- 建表时指定:
CREATE TABLE t (...) AUTO_INCREMENT = 1000; - 已有表修改:
ALTER TABLE t AUTO_INCREMENT = 1000;(注意:该值不能小于当前最大id,否则会被忽略) - 清空并重置:
TRUNCATE TABLE t;(会重置计数器;DELETE FROM t不会)
另外,SHOW TABLE STATUS LIKE 't' 查出的 Auto_increment 字段才是真实下一次分配值,比查 MAX(id) 更准——尤其当有事务回滚或批量失败时,MAX(id) 会严重误导。
bigint 比 int 更值得默认选用
INT 有符号上限是 2147483647,约 21 亿;一旦业务增长快,几年就可能撞墙。而 BIGINT 上限是 9223372036854775807,够用几十年。性能差异在现代硬件上几乎可忽略,但溢出后果是灾难性的(插入失败、应用报错、数据丢失)。
所以建议统一用:
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY
加 UNSIGNED 能把正数范围翻倍,且主键天然非负,没必要浪费一半空间存负数。
真正麻烦的从来不是语法,而是字段类型选小了、没加 NOT NULL、或者误以为 DELETE 能重置自增——这些细节一错,后续修复成本远高于一开始多敲几个字符。











