科普文:软件架构数据库系列之【MySQL解析器和优化器】-CSDN博客
科普文:软件架构数据库系列之【MySQL查询优化器中的优化策略optimizer_switch】-CSDN博客
科普文:软件架构数据库系列之【MySQL执行计划Extra梳理】-CSDN博客
科普文:软件架构数据库系列之【MySQL控制查询优化器Hints】-CSDN博客
从MySQL的解析器、优化器、执行计划、Hints、到最后的执行器,都绕不开sql_mode。
sql_mode是MySQL的一个系统变量,用于设置服务器对SQL语句的解析和执行规则。
它可以影响MySQL的行为,包括语法规范、数据校验、数据类型转换和错误处理等。
sql_mode是个很容易忽视的变量,默认值是空值,在这种设置下是可以允许一些非法操作的,比如允许一些非法数据的插入。在生产环境必须将这个值设置为严格模式,所以开发、测试环境的数据库也必须要设置,这样在开发测试阶段就可以发现问题。
本文介绍sql_mode的参数取值规则和取值解释,您可以根据实际业务进行调整。
1)通过设置sql mode,可以完成不同严格程度的数据校验。
2)通过设置sql mode为宽松模式,来保证大多数sql符合标准的sql语法,这样应用在不同数据库之间进行迁移时,则不需要对业务sql进行较大的修改。
3)在不同数据库之间进行数据迁移之前,通过设置SQL Mode可以使MySQL上的数据更方便地迁移到目标数据库中。
模式 | 含义 |
---|---|
ONLY_FULL_GROUP_BY | 对于GROUP BY聚合操作,如果在SELECT中的列,没有在GROUP BY 中出现,那么这个SQL是不合法的,因为列不在GROUP BY从句中。 |
NO_AUTO_VALUE_ON_ZERO | 该值影响自增长列的插入。默认设置下,插入0或NULL代表生成下一个自增长值。如果用户希望插入的值为0,而该列又是自增长的,那么这个选项就有用了。 |
STRICT_TRANS_TABLES | 严格模式,在该模式下,如果一个值不能插入到一个事务表中,则中断当前的操作,对非事务表不做限制。 |
NO_ZERO_IN_DATE | 在严格模式下,不允许日期和月份为零。 |
NO_ZERO_DATE | 该值会使得MySQL数据库不允许插入零日期,插入零日期会抛出错误而不是警告。 |
ERROR_FOR_DIVISION_BY_ZERO | 在INSERT或UPDATE过程中,如果数据被零除,则产生错误而非警告。如果未给出该模式,那么数据被零除时MySQL返回NULL |
NO_AUTO_CREATE_USER | 禁止GRANT创建密码为空的用户 |
NO_ENGINE_SUBSTITUTION | 如果需要的存储引擎被禁用或未编译,那么抛出错误。不设置此值时,用默认的存储引擎替代,并抛出一个异常 |
PIPES_AS_CONCAT | 将双竖线符号视为字符串的连接操作符而非 “或” 运算符,这个在Oracle中缺省支持通过来双竖线符号实现字符串拼接,不过在MySQL默认不支持,需要设置sql_mode模式为PIPES_AS_CONCAT才可以 |
ANSI_QUOTES | 启用ANSI_QUOTES后,不能用双引号来引用字符串,因为它被解释为识别符 |
1)注意MySQL5.6和MySQL5.7默认的sql_mode模式参数是不一样的。
5.6的mode是NO_ENGIN_SUBSTITUTION,表示一个空值,相当于没有模式设置,可以理解为宽松模式。5.7的mode是STRICT_TRANS_TABLES,也就是严格模式。
2)如果设置的
通常在开发、测试、生产环境都应该要采用严格模式,这样我们在开发测试阶段就能及早发现问题,宽松模式只应该在数据库迁移的时候,为了不需要对sql进行大改的特殊情况下才使用。
1)先执行select@@sql_mode,复制查询出来的值,并将其中的NO_ZERO_IN_DATE,NO_ZERO_DATE删除,然后执行set sql_mode = ‘修改后的值’或者set session sql_mode='修改后的值';
这个方法只在当前会话中生效,重启MySQL服务后失效。
2)先执行select@@global.sql_mode,复制查询出来的值并将其中的NO_ZERO_DATE_IN_DATE,NO_ZERO_DATE删除,然后执行set global sql_mode = '修改后的值'。
此方法在当前服务中生效,重启MySQL服务后失效。
3)在mysql的安装目录下,或my.cnf文件(windows系统的话是my.ini文件),新增sql_mode=ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION.
[mysqld]
sql_mode=ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER
然后重启MySQL服务
这个方法永久生效的,当然生产环境是禁止重启MySQL服务的,所以同时采用方式二和方式三,哪天异常重启后,也随之永久生效了。
sql_mode参数的取值支持以下参数的自由组合,使用英文逗号连接。
REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH,NO_AUTO_CREATE_USER,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,MYSQL323,MYSQL40,ANSI,TRADITIONAL
sql_mode参数的取值支持以下参数的自由组合,使用英文逗号连接。
REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH,NO_AUTO_CREATE_USER,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,MYSQL323,MYSQL40,ANSI,TRADITIONAL
sql_mode参数的取值支持以下参数的自由组合,使用英文逗号连接。
REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH,ANSI,TRADITIONAL
在sql_mode参数的取值中,一定的参数组合称为组合SQL模式。组合SQL模式的详情如下表所示。
组合SQL模式名称 |
解释 |
DB2 |
等同于 重要 从MySQL 5.7.22开始,DB2就被弃用了,并且在MySQL 8.0中被删除。 |
MSSQL |
等同于 |
POSTGRESQL |
等同于 重要 从MySQL 5.7.22开始,POSTGRESQL已被弃用,并且在MySQL 8.0中被删除。 |
ORACLE |
等同于 重要 从MySQL 5.7.22开始,ORACLE已被弃用,并且在MySQL 8.0中被删除。 |
MAXDB |
等同于 重要 从MySQL 5.7.22开始,MAXDB已被弃用,并且在MySQL 8.0中被删除。 |
MYSQL323 |
等同于
重要 从MySQL 5.7.22开始,MYSQL323已被弃用,并且在MySQL 8.0中被删除。 |
MYSQL40 |
等同于
重要 从MySQL 5.7.22开始,不推荐使用MYSQL40,并且在MySQL 8.0中被删除。 |
ANSI |
等同于 |
TRADITIONAL |
|
参数值 |
MySQL 5.6 |
MySQL 5.7 |
MySQL 8.0 |
含义 |
ALLOW_INVALID_DATES |
支持 |
支持 |
支持 |
允许插入或更新无效的日期值,即不符合日期格式的值。 在默认的严格模式下,MySQL要求日期值必须符合指定的格式,例如 但是,当设置 说明 此模式适用于 示例: 假设有一个日期字段"birthday",在严格模式下,只能插入 重要
|
ANSI_QUOTES |
支持 |
支持 |
支持 |
用于启用 在使用sql_mode默认值时,MySQL使用单引号('')来引用字符串值,使用反引号(``)来引用标识符(如表名、列名)。例如: 而当设置 启用 重要 并非所有的数据库都支持使用双引号引用标识符,因此在使用 |
ERROR_FOR_DIVISION_BY_ZERO |
支持 |
支持 |
支持 |
用于在进行除零运算时发出警告(或者错误)而不是返回NULL值。
对于数据更改操作(
对于
重要 启用 |
HIGH_NOT_PRECDENCE SQL |
支持 |
支持 |
支持 |
用于提高 默认情况下, 在一些旧版本的MySQL中, 可以通过 |
IGNORE_SPACE |
支持 |
支持 |
支持 |
允许函数名称和
|
NO_AUTO_VALUE_ON_ZERO |
支持 |
支持 |
支持 |
用于禁止将自动递增列的默认值设置为0。 在默认情况下,当插入一行数据时,如果自动递增列的值被设置为0,MySQL会自动将其替换为下一个可用的自动递增值。然而,当设置 这个参数的作用是为了避免意外地将0作为自动递增列的默认值。在某些情况下,将自动递增列的默认值设置为0可能会导致数据不一致或错误的结果。 例如: 如果 然而,当设置 在这种情况下,MySQL将返回错误并拒绝将0作为自动递增列的默认值。 说明
|
NO_BACKSLASH_ESCAPES |
支持 |
支持 |
支持 |
用于禁止使用反斜杠(\)进行转义。 在默认情况下,MySQL允许使用反斜杠作为转义字符,在字符串中插入特殊字符或转义字符本身。例如,可以使用 然而,当设置 这个参数的作用是为了避免使用反斜杠进行转义可能引起的混淆和错误。有时,使用反斜杠进行转义可能会导致意外的结果,特别是在处理包含大量反斜杠的数据时。 例如: 在默认情况下,上述查询中的两个单引号之间的反斜杠是用于转义的。然而,当设置 说明
|
NO_DIR_IN_CREATE |
支持 |
支持 |
支持 |
用于在 在默认情况下, 该参数的作用是为了限制或防止在 例如: 如果 在主从复制场景下,可在从库上开启该mode。 说明
|
NO_ENGINE_SUBSTITUTION |
支持 |
支持 |
支持 |
用于在创建或修改表时禁止使用默认存储引擎的替代。 在MySQL中,如果在创建或修改表时指定的存储引擎不可用或不支持,MySQL会自动替换为默认的存储引擎。然而,当设置 该参数的作用是为了确保使用指定的存储引擎,并避免意外或不一致的存储引擎替换。 例如: 如果 说明
|
NO_UNSIGNED_SUBTRACTION |
支持 |
支持 |
支持 |
用于禁止在无符号整数之间执行结果为负数的减法运算。 整数值之间的相减(其中一个为 然而,当设置sql_mode为 该参数的作用是为了避免在无符号整数之间执行减法运算时产生意外的结果。在某些情况下,无符号整数之间的减法运算可能会导致负数的结果,这可能与预期不符。 例如: 如果 重要 启用 |
NO_ZERO_DATE |
支持 |
支持 |
支持 |
用于禁止在日期或日期时间列中使用 在默认情况下,MySQL允许在日期或日期时间列中使用
该参数的作用是为了避免使用无效或不合适的日期值。 例如: 如果 说明
|
NO_ZERO _IN_DATE |
支持 |
支持 |
支持 |
用于控制是否允许年的部分为非零,但月或日的部分为0的日期。 说明 此模式会影响日期如
|
ONLY_FULL_GROUP_BY |
支持 |
支持 |
支持 |
用于设置 在默认情况下,MySQL允许在 在这个查询中, 当设置 例如,下面的查询在ONLY_FULL_GROUP_BY模式下会返回错误: 在这个查询中, 通过启用 说明
|
PAD_CHAR_TO_FULL_LENGTH |
支持 |
支持 |
支持 |
用于控制不删除 在对 如果启用了 重要 此模式不适用于 |
PIPES_AS_CONCAT |
支持 |
支持 |
支持 |
将 |
REAL_AS_FLOAT |
支持 |
支持 |
支持 |
将 默认情况下,MySQL将 |
STRICT_ALL_TABLES |
支持 |
支持 |
支持 |
为所有存储引擎启用严格的SQL模式,无效的数据值会被拒绝。 在默认情况下,MySQL允许一些隐式的数据类型转换和插入、更新操作中的警告。但是,当设置 启用
使用 重要 启用 说明 从MySQL 5.7.4到5.7.7, |
STRICT_TRANS_TABLES |
支持 |
支持 |
支持 |
为事务存储引擎启用严格的SQL模式。具体解释参见上文的 重要 启用 说明 从MySQL 5.7.4到5.7.7, |
NO_AUTO_CREATE_USER |
支持 |
支持 |
不支持 |
用于禁止在 在默认情况下,MySQL允许在 该参数的作用是在安全性方面提供更严格的控制。通过禁止自动创建用户,可以确保只有已经存在的用户才能被授权访问数据库。 例如: 如果new_user用户不存在,但 然而,当设置 需要注意的是, 说明 在MySQL 8.0中,已不允许 |
NO_FIELD_OPTIONS |
支持 |
支持 |
不支持 |
不允许在 |
NO_KEY_OPTIONS |
支持 |
支持 |
不支持 |
不允许在 |
NO_TABLE_OPTIONS |
支持 |
支持 |
不支持 |
不允许在 |