📊 MySQL sql_mode 模式对比 (MySQL 5.7 vs 8.0)
sql_mode 是 MySQL 中一个非常重要的系统变量,它定义了 MySQL 如何处理语法和数据的有效性,以实现不同的 SQL 行为。MySQL 8.0 在 sql_mode 上进行了一些重要的调整,主要是 默认开启了更严格的模式,并移除了一些过时的模式。
以下表格对比了 MySQL 5.7 和 8.0 版本中关键 sql_mode 模式的支持情况和差异:
| sql_mode 模式 | MySQL 5.7 支持 | MySQL 8.0 支持 | 差异说明及作用 |
|---|---|---|---|
STRICT_TRANS_TABLES | ✅ 支持 (非默认) | ✅ 支持 (默认) | 严格模式。 关键模式。如果在新行中插入无效或缺失的值,MySQL 会给出错误(而非警告并插入 null),并回滚事务。 |
NO_ZERO_DATE | ✅ 支持 (非默认) | ❌ 移除(被合并到严格模式) | 禁止使用 '0000-00-00' 作为合法日期。在 8.0 中,行为已成为严格模式的一部分。 |
NO_ZERO_IN_DATE | ✅ 支持 (非默认) | ❌ 移除(被合并到严格模式) | 禁止日期(如 YYYY-MM-DD)的月份或日期部分为零。在 8.0 中,行为已成为严格模式的一部分。 |
ONLY_FULL_GROUP_BY | ✅ 支持 (默认) | ✅ 支持 (默认) | 关键模式。 强制要求 SELECT 列表、HAVING 或 ORDER BY 中的所有非聚合列都必须出现在 GROUP BY 子句中。 |
NO_ENGINE_SUBSTITUTION | ✅ 支持 (默认) | ✅ 支持 (默认) | 如果用户指定的存储引擎不可用,则抛出错误。 |
NO_AUTO_CREATE_USER | ✅ 支持 (非默认) | ❌ 移除 | 用于阻止 GRANT 语句自动创建用户。在 8.0 中,必须使用 CREATE USER 语句创建用户。 |
TRADITIONAL | ✅ 支持 | ✅ 支持 | 最严格模式。 相当于 STRICT_TRANS_TABLES, STRICT_ALL_TABLES, NO_ZERO_DATE, NO_ZERO_IN_DATE, ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER 的组合(具体组合版本略有不同)。 |
ALLOW_INVALID_DATES | ✅ 支持 | ✅ 支持 | 不检查月份是否在 1-12 之间,或日期是否在 1-31 之间。仅检查年份和天数范围。 |
ERROR_FOR_DIVISION_BY_ZERO | ✅ 支持 (非默认) | ✅ 支持 (默认) | 在插入或更新时,如果发生除零操作,则抛出错误。 |
重点变化总结 (5.7 迁移到 8.0 需注意)
- 更严格的默认模式: MySQL 8.0 的默认
sql_mode包含STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,ONLY_FULL_GROUP_BY等。这使得 8.0 开箱即用 就比 5.7 更严格。 - 零日期(Zero Dates)处理: 模式
NO_ZERO_DATE和NO_ZERO_IN_DATE在 8.0 中被移除,它们的行为已被内置到严格模式 (STRICT_TRANS_TABLES和TRADITIONAL) 中。如果您的应用在 5.7 中依赖于插入'0000-00-00'日期且未开启严格模式,迁移到 8.0 默认模式下会导致错误。 - 用户创建:
NO_AUTO_CREATE_USER模式被移除,因为它在 8.0 中已成为强制行为。您不能再通过GRANT语句隐式创建用户。
在从 MySQL 5.7 升级到 8.0 时,建议您在新环境中仔细测试,以确保应用不会因为默认开启的严格模式(如 ONLY_FULL_GROUP_BY 和日期检查)而引发错误。