MySQL关闭sql_mode的only_full_group_by

📅 2026/8/1 9:42:23
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_BYSTRICT_TRANS_TABLESNO_ZERO_IN_DATENO_ZERO_DATEERROR_FOR_DIVISION_BY_ZERONO_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例子指定 ENGINEInnoDB但服务器不支持语句会失败。配置建议生产环境强烈建议启用严格模式至少包含 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