MySQL关闭sql_mode的only_full_group_by

📅 2026/8/1 9:55:24 👁️ 阅读次数 📝 编程学习
MySQL关闭sql_mode的only_full_group_by

MySQL 的 sql_mode 系统变量,简单来说,就是一套用来控制 MySQL 行为“严格程度”的规则。它决定了 MySQL 接受什么样的 SQL 语法,以及数据插入或更新时要不要进行严格的合法性检查。

sql_mode 的作用范围和配置方式如下:

作用域:它可以设置为全局(影响所有新连接),也可以设置为会话(只影响当前客户端连接)。

查看当前模式:使用 SELECT @@sql_mode; 或 SELECT @@GLOBAL.sql_mode;

运行时修改命令如下:

SET GLOBAL sql_mode = 'modes'; (需要管理权限,只影响后续新连接)

SET SESSION sql_mode = 'modes'; (只影响当前会话)

默认模式与关键选项
不同版本的 MySQL 默认值可能不同。从 MySQL 8.0 开始(到 9.7 版本),默认的 sql_mode 通常包含以下几项:

ONLY_FULL_GROUP_BY

STRICT_TRANS_TABLES

NO_ZERO_IN_DATE

NO_ZERO_DATE

ERROR_FOR_DIVISION_BY_ZERO

NO_ENGINE_SUBSTITUTION

模式 (Mode)主要作用
STRICT_TRANS_TABLES“严格模式” 的核心。当插入或更新数据不符合列的定义时(如字符串超长、类型不匹配),会直接报错并中止操作,而不是只给一个警告然后自动截断或转换。
ONLY_FULL_GROUP_BY强制 SELECT 语句中,不在 GROUP BY 子句中的非聚合列,不能出现在 SELECT 列表中。
NO_ZERO_DATE禁止使用 '0000-00-00' 作为合法的日期值。
NO_ZERO_IN_DATE禁止日期中出现零值月或日(如 '2023-00-01' 或 '2023-01-00')。
ERROR_FOR_DIVISION_BY_ZERO控制除零操作的处理。在严格模式下,除零会报错;否则返回 NULL 并给出警告。
NO_ENGINE_SUBSTITUTION当 CREATE TABLE 或 ALTER TABLE 指定的存储引擎不可用时,直接报错,而不是自动替换为默认引擎
其他除了上述,还有一些组合模式,比如 TRADITIONAL,它就像是“严格模式”的集合,让 MySQL 的行为更像传统的 SQL 数据库,对非法数据会直接报错,而不是给警告。

STRICT_TRANS_TABLES例子:

尝试将一个100字符的字符串插入到一个VARCHAR(10)列中,会直接报错,而不是被截断保存。

ONLY_FULL_GROUP_BY例子:

SELECT name, age, MAX(score) FROM students GROUP BY name; 这条语句会报错,因为 age 没有出现在 GROUP BY 中。

NO_ZERO_DATE例子:

插入 '0000-00-00' 到 DATE 类型的列会报错或警告(取决于是否在严格模式下)。

NO_ZERO_IN_DATE例子:

与严格模式结合会报错,否则可能会被转为 '0000-00-00' 并给出警告。

ERROR_FOR_DIVISION_BY_ZERO例子:

SELECT 1/0; 在严格模式下会直接报错。

NO_ENGINE_SUBSTITUTION例子:

指定 ENGINE=InnoDB,但服务器不支持,语句会失败。

配置建议
生产环境:强烈建议启用严格模式,至少包含 STRICT_TRANS_TABLES。这是保证数据质量的第一道防线,可以避免很多因为数据“悄悄”被截断或转换而引发的逻辑错误。

开发环境:为了尽早发现问题,最好能让开发环境与生产环境的 sql_mode 保持一致。如果为了调试方便,可以适当放宽,但最终上线前务必切换到严格模式。
注意事项
分区的风险:如果在创建了包含用户自定义分区的表之后,再更改 sql_mode,可能导致数据丢失或损坏。官方强烈建议,一旦创建了分区表,就不要再变更 sql_mode。

主从环境:为了数据一致性,主库和从库的 sql_mode 设置最好完全相同。

永久修改sql_mode方法(需要重启)

找到配置文件:通常是Linux下的 my.cnf 以及include相关的配置文件文件

修改配置:在 [mysqld] 部分,找到 sql_mode 这一行,将 ONLY_FULL_GROUP_BY 从列表中删除。如果没有这一行,可以自行添加。

操作建议:最好先通过 SELECT @@sql_mode; 查看当前完整的模式列表,复制出来,再删掉 ONLY_FULL_GROUP_BY 后填入配置文件,避免遗漏。
[mysqld]
sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION

保存后重启mysql服务。

systemctl restart mysqld.service