MySQL 8.0 默认启用 STRICT_TRANS_TABLES 和 ONLY_FULL_GROUP_BY,导致 INSERT 缺失非空字段值或 GROUP BY 查询不合规时报错;应补全字段、重写查询或调整表结构,而非关闭严格模式。
MySQL 5.7 升级到 8.0 后
报错
这是最典型的严格模式触发问题:MySQL 8.0 默认启用
,而旧版本可能关闭或仅部分启用。当表中某列定义为
且无默认值,但
语句又没显式提供该列值时,8.0 直接拒绝写入。
实操建议:
先查当前模式:
,重点看是否含
或
临时绕过(仅调试):
,但不解决根本问题
长期方案不是关严格模式,而是补全缺失字段——检查应用层
语句,确保所有
列都有值或明确设为
若字段确实允许空,改表结构:
,而非降级 SQL 模式
为什么
在 MySQL 8.0 报错
这是因为
在 8.0 成为默认模式之一。它强制要求
列必须是
中的列、聚合函数结果,或功能依赖于分组列的表达式。
常见错误场景:用
——
和
不在
中,也不被聚合,MySQL 无法确定返回哪一行的值。
实操建议:
别直接删
:它能暴露查询逻辑缺陷,关掉反而掩盖数据歧义
重写查询:要么把
、
加进
,要么用聚合函数包裹,如
若业务真需要“每组任取一行”,用窗口函数更清晰:
+ 外层过滤
确认兼容性:低版本 MySQL 可能不支持窗口函数,需评估客户端 MySQL 驱动和服务器版本匹配
配置写在 my.cnf 里却没生效?
配置项加载顺序和作用域容易混淆:全局配置文件(
或
)只影响服务启动时的默认值;已运行实例需手动刷新,且用户会话可覆盖全局设置。
MySQL(Linux)
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
下载
实操建议:
检查实际生效值用
和
,二者可能不同
修改
后必须重启 MySQL 服务,
仅临时生效,重启即丢失
避免混用:不要在
里写
,又在应用连接后执行
,后者会完全覆盖前者
生产环境推荐最小化模式:保留
和
,去掉过时的
(8.0.11+ 已废弃)
PHP/Python 应用连上 MySQL 8.0 后日期插入变
或报错
这通常由
和
导致。老应用常习惯传
表示“无日期”,但新 MySQL 拒绝该值并抛异常,或静默转成
(取决于其他模式组合)。
实操建议:
别依赖
:它是非标准值,PostgreSQL / SQL Server 均不支持,应统一用
检查 ORM 配置:Laravel 的
、Django 的
是否正确设置;SQLAlchemy 是否启用了
如果必须兼容旧数据,可在建表时显式允许零日期:
,再配合应用层校验
注意时区交互:PHP 的
下,时间字符串解析受 MySQL 服务端
影响,和
无关但常被误判
真正麻烦的不是模式开关本身,而是那些藏在 ORM 自动生成 SQL 里的隐式假设——比如认为
字段总能靠数据库默认值兜底,或相信
会稳定返回第一行。这些在宽松模式下跑得欢,一开严格模式就露馅。
INSERTField 'xxx' doesn't have a default valueSTRICT_TRANS_TABLESNOT NULLINSERTSELECT @@sql_mode;STRICT_TRANS_TABLESSTRICT_ALL_TABLESSET SESSION sql_mode = '';INSERTNOT NULLDEFAULTALTER TABLE t MODIFY col VARCHAR(20) NULL;GROUP BYExpression #1 of SELECT list is not in GROUP BY clauseONLY_FULL_GROUP_BYSELECTGROUP BYSELECT id, name, COUNT(*) FROM user GROUP BY dept_id;idnameGROUP BYONLY_FULL_GROUP_BYidnameGROUP BYMAX(name)ROW_NUMBER() OVER (PARTITION BY dept_id ORDER BY id) rnrn = 1sql_mode/etc/my.cnf/usr/etc/my.cnfSELECT @@GLOBAL.sql_mode;SELECT @@SESSION.sql_mode;my.cnfSET GLOBALmy.cnfsql_mode=STRICT_TRANS_TABLES,NO_ZERO_DATESET SESSION sql_mode = ''STRICT_TRANS_TABLESONLY_FULL_GROUP_BYNO_AUTO_CREATE_USER0000-00-00NO_ZERO_DATENO_ZERO_IN_DATE'0000-00-00'NULL0000-00-00NULL$datesblank=True, null=Truedefault=NoneCREATE TABLE ... date_col DATE NULL DEFAULT NULLPDO::ATTR_EMULATE_PREPARES = falsetime_zonesql_modeNOT NULLGROUP BY