应为id字段未设AUTO_INCREMENT且严格模式启用,需优先添加AUTO_INCREMENT而非关闭严格模式;可通过ALTER TABLE MODIFY语句修复,并确保字段类型正确、无重复或NULL值。

MySQL严格模式导致INSERT报错Field 'id' doesn't have a default value
这是典型严格模式(STRICT_TRANS_TABLES 或 STRICT_ALL_TABLES)起效的表现:当表中 id 是 NOT NULL 且没设 DEFAULT,又没在 INSERT 里显式提供值时,MySQL 直接拒绝写入,而不是像旧版本那样静默填 0 或空字符串。
常见场景包括:用 ORM 自动生成 INSERT(如 Django、Laravel 默认不传主键)、迁移老代码到新 MySQL 版本(8.0+ 默认开启严格模式)、或手动建表时漏写 AUTO_INCREMENT。
- 别急着关严格模式——先确认
id字段是否本该是自增主键:如果是,加AUTO_INCREMENT比关模式更安全 - 如果确定要关,只关当前会话最稳妥:
SET SESSION sql_mode = '';(重启后自动恢复) - 全局关闭需改配置文件(
my.cnf或mysqld.cnf),在[mysqld]下加sql_mode = "",但会影响所有应用,不推荐 - MySQL 8.0+ 的默认
sql_mode包含STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,删掉前者即可,不必清空全部
检查当前sql_mode并定位严格模式开关
直接查生效的模式,比猜配置更可靠:
SELECT @@sql_mode;
输出里只要看到 STRICT_TRANS_TABLES 或 STRICT_ALL_TABLES,就是它在拦截你的 INSERT。
-
@@sql_mode返回的是逗号分隔的字符串,注意区分大小写和拼写(比如不是STRICT_MODE) - 会话级设置优先于全局,所以即使配置文件没开,也可能被客户端连接时带的 init-command 或 ORM 驱动自动设置了
- Docker 环境下,
MYSQL_SQL_MODE环境变量会覆盖配置文件,记得一并检查
ALTER TABLE加AUTO_INCREMENT比关严格模式更治本
如果 id 本意就是主键自增,关模式只是绕过问题,而补自增才是修复根源。
执行前先确认字段类型和键状态:
SHOW CREATE TABLE your_table_name;
- 字段必须是整型(如
INT、BIGINT),且未被其他键引用(否则加自增会失败) - 若已有数据,确保
id值不重复且无NULL;否则先用UPDATE补全再加AUTO_INCREMENT - 正确语法:
ALTER TABLE your_table_name MODIFY id INT AUTO_INCREMENT PRIMARY KEY FIRST;(注意MODIFY会重定义整个字段,CHANGE可改名,别漏PRIMARY KEY) - 加完后,下次
INSERT INTO your_table_name (name) VALUES ('test');就能自动生成id,无需关任何模式
ORM或框架里隐式触发严格模式的坑
很多框架默认不传主键字段,但 MySQL 8.0+ 严格模式下直接报错,表面看是数据库问题,实际是交互逻辑不匹配。
- Django:确保模型字段有
primary_key=True且数据库列已设AUTO_INCREMENT,否则save()会因缺失id被拒 - Laravel Eloquent:检查迁移文件里是否写了
$table->id()或$table->increments('id'),对应生成AUTO_INCREMENT - 直连 MySQL 的脚本(如 Python + PyMySQL):确认
cursor.execute()的 SQL 是否漏了字段,或参数占位符数量与字段数不一致 - 某些低代码平台或可视化工具生成的 INSERT 语句,可能硬编码了字段列表却没包含
id,此时关模式只是掩耳盗铃
真正麻烦的不是关不关模式,而是不同环境(开发/测试/生产)的 sql_mode 不一致,导致本地跑得通,上线就报错。务必把 sql_mode 纳入部署检查清单。


















