MySQL中的sql_mode

41 阅读3分钟

📊 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 列表、HAVINGORDER 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 需注意)

  1. 更严格的默认模式: MySQL 8.0 的默认 sql_mode 包含 STRICT_TRANS_TABLES, ERROR_FOR_DIVISION_BY_ZERO, NO_ENGINE_SUBSTITUTION, ONLY_FULL_GROUP_BY 等。这使得 8.0 开箱即用 就比 5.7 更严格。
  2. 零日期(Zero Dates)处理: 模式 NO_ZERO_DATENO_ZERO_IN_DATE 在 8.0 中被移除,它们的行为已被内置到严格模式 (STRICT_TRANS_TABLESTRADITIONAL) 中。如果您的应用在 5.7 中依赖于插入 '0000-00-00' 日期且未开启严格模式,迁移到 8.0 默认模式下会导致错误。
  3. 用户创建: NO_AUTO_CREATE_USER 模式被移除,因为它在 8.0 中已成为强制行为。您不能再通过 GRANT 语句隐式创建用户。

在从 MySQL 5.7 升级到 8.0 时,建议您在新环境中仔细测试,以确保应用不会因为默认开启的严格模式(如 ONLY_FULL_GROUP_BY 和日期检查)而引发错误。