MySQL配置sql_mode的参数属性作用

 更新时间:2024年07月05日 10:10:29   作者:码农老张Zy  
,通过设置sql_mode,可以完成不同严格程度的数据校验,本文主要介绍了MySQL配置sql_mode的作用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

不知道你有没有踫到过这种问题,在 MySQL8 默认的情况下,我们之前习惯的为 DateTime 类型指定的 0000-00-00 这种格式是无法插入或者修改数据的。其实这种情况就是 MySQL 模式设置的问题,也就是我们今天要讲的 sql_mode 这个参数属性的作用。

sql_mode

根据官网的解释,MySQL 服务器是可以在不同的 SQL 模式中运行的,这个模式会影响 MySQL 支持的 SQL 语法及其执行的数据验证检查。通过模式的设置,可以让不同环境中使用 MySQL 以及其他数据库服务器一起使用 MySQL 变得更加容易。并且,MySQL 可以将这些模式分别运用于不同的客户端,也就是说,它是有 SESSION 会话设置能力的一个系统变量。

如何查看当前系统的 sql_mode 呢?和查看系统变量是一样的。

mysql> SHOW VARIABLES LIKE 'sql_mode';
+---------------+-----------------------------------------------------------------------------------------------------------------------+
| Variable_name | Value                                                                                                                 |
+---------------+-----------------------------------------------------------------------------------------------------------------------+
| sql_mode      | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION |
+---------------+-----------------------------------------------------------------------------------------------------------------------+
1 row in set (0.19 sec)

这是我们在虚拟机上通过 RPM 安装的 MySQL ,没有对 sql_mode 进行其它的修改,因此这就是默认的参数。默认情况下,MySQL8 的 sql_mode 就是这些内容。

设置 sql_mode

我们新建一个表,尝试一下日期相关的操作。

CREATE TABLE `test_mode` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `created_at` datetime NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

接下来,我们插入一条数据。

mysql> insert into test_mode values(null,'0000-00-00 00:00:00');
ERROR 1292 (22007): Incorrect datetime value: '0000-00-00 00:00:00' for column 'created_at' at row 1

很明显,默认情况下,0000 这种形式插入日期是不行的,这时我们就可以修改 sql_mode ,让它回到 MySQL5 的时代,可以直接插入这种形式的日期数据。

[server]
sql_mode=ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION

我们可以通过上面的方式直接修改 my.cnf 文件,当然也可以通过 SET sql_mode=xxx 的形式在命令行中动态修改,如果是修改的 my.cnf 文件,则需要重启 MySQL 服务,再次执行插入语句。

mysql> insert into test_mode values(null,'0000-00-00 00:00:00');
Query OK, 1 row affected (0.03 sec)

mysql> select * from test_mode;
+----+---------------------+
| id | created_at          |
+----+---------------------+
|  1 | 0000-00-00 00:00:00 |
+----+---------------------+
1 row in set (0.00 sec)

如果你之前的数据库是老版本的,现在迁移到 MySQL8 的话,那么去掉 sql_mode 中的 NO_ZERO_IN_DATE 和 NO_ZERO_DATE 参数就可以了,NO_ZERO_DATE 代表是否允许 0000 这种格式,而 NO_ZERO_IN_DATE 则是针对日期和月份部分是否为 00 。

其它的参数其实通过名字我们也能看出来个大概,ERROR_FOR_DIVISION_BY_ZERO 表示除 0 相关的信息,如果插入或更新数据时有除 0 相关操作,比如 MOD(2,0) 这样,就会报出警告。

mysql> insert into test_mode values(mod(2,0),'0000-00-00 00:00:00');
ERROR 1365 (22012): Division by 0

ONLY_FULL_GROUP_BY 表示拒绝在 SELECT、HAVING 或 GROUP BY 中引用聚合列的查询。看不懂没关系,我们直接看下面的例子。

-- 有 ONLY_FULL_GROUP_BY
mysql> select sum(id), created_at from test_mode;
ERROR 1140 (42000): In aggregated query without GROUP BY, expression #2 of SELECT list contains nonaggregated column 'ma_test.test_mode.created_at'; this is incompatible with sql_mode=only_full_group_by

-- 删掉 ONLY_FULL_GROUP_BY
mysql> select sum(id), created_at from test_mode;
+---------+---------------------+
| sum(id) | created_at          |
+---------+---------------------+
|       6 | 0000-00-00 00:00:00 |
+---------+---------------------+
1 row in set (0.00 sec)

STRICT_TRANS_TABLES 表示为事务性存储引擎启用严格的SQL模式,如果可能,也为非事务性存储引擎启用严格的SQL模式。这里提到了一个严格模式的概念,严格模式控制 MySQL 如何处理 INSERT 或 UPDATE 等更改语句中的无效或缺失值,比如上面我们说过的日期和除零问题,如果没有 STRICT_TRANS_TABLES 的话,即使有 NO_ZERO_DATE 和 ERROR_FOR_DIVISION_BY_ZERO 参数,也不会出现错误信息。此外,严格模式还会影响到建表和修改表的语句,也就是 CREATE 和 ALTER 语句。

mysql> set sql_mode='NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> SHOW VARIABLES LIKE 'sql_mode';
+---------------+--------------------------------------------------------------------------------+
| Variable_name | Value                                                                          |
+---------------+--------------------------------------------------------------------------------+
| sql_mode      | NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION |
+---------------+--------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> insert into test_mode values(mod(2,0) ,'0000-00-00 00:00:00');
Query OK, 1 row affected, 1 warning (0.29 sec)

最后一个 NO_ENGINE_SUBSTITUTION 则是在创建或者修改表时,如果指定了一个不存在的表引擎,是报错还是使用默认引擎替换并警告。

除了上面这些内容之外,sql_mode 还有很多设置,我们再来演示一个 NO_AUTO_VALUE_ON_ZERO 。默认情况下,我们进行数据插入时,给自增长列指定 null 或者 0 ,都会从1开始正常自动增长,但现在我们让 0 不是产生自增长,而是确定的插入一个 0 ,就可以使用这个参数。

mysql> set sql_mode='xxxxxxx,NO_AUTO_VALUE_ON_ZERO';
Query OK, 0 rows affected (0.00 sec)

mysql> insert into test_mode values(0, null);
Query OK, 1 row affected (0.00 sec)

mysql> insert into test_mode values(0, null);
ERROR 1062 (23000): Duplicate entry '0' for key 'test_mode.PRIMARY'

mysql> select id, created_at from test_mode;
+----+---------------------+
| id | created_at          |
+----+---------------------+
|  0 | NULL                |
|  1 | 0000-00-00 00:00:00 |
|  2 | 0000-00-00 00:00:00 |
|  3 | 0000-00-00 00:00:00 |
|  4 | NULL                |
|  5 | NULL                |
|  6 | 0000-00-00 00:00:00 |
|  7 | 0000-00-00 00:00:00 |
|  8 | 0000-00-00 00:00:00 |
|  9 | NULL                |
| 10 | NULL                |
+----+---------------------+
11 rows in set (0.00 sec)

可以看到在数据中,有了一条 id 为 0 的数据,如果再次插入的话,就会报主键重复,现在 0 就会被当成一个正常的数字 0 ,而不会转化成为 null 的形式进行自动增长操作。

总结

今天的内容简单地介绍了一下 sql_mode 这个属性相关的作用以及一些常用的参数设置。另外还有一部分设置可能使用得比较少,而且大部分情况下我们也不太会去修改这一块的配置,所以大家了解一下即可。在转移或升级到 MySQL8 之后,其实最常见的问题就是上面说过的日期问题,0格式日期这种形式其实是已经过时的方式了,也是不推荐的方式,所以在 MySQL8 中会默认在严格模式下禁用这种形式的日期存储,这一点也是大家需要注意的,能使用正常日期或者使用 null 最好,另外数字时间戳存 0 也是可以表示这类空日期格式的,具体需求还是看你的业务情况来具体分析哦。

参考文档:

https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html

到此这篇关于MySQL配置sql_mode的作用的文章就介绍到这了,更多相关MySQL配置sql_mode内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • mysql 中如何取得汉字字段的各汉字首字母

    mysql 中如何取得汉字字段的各汉字首字母

    这篇文章主要介绍了mysql中如何取得汉字字段的各汉字首字母,需要的朋友可以参考下
    2014-08-08
  • mysql ERROR 1044 (42000): Access denied for user ''''@''localhost'' to database

    mysql ERROR 1044 (42000): Access denied for user ''''@''loca

    这篇文章主要介绍了mysql下提示ERROR 1044 (42000): Access denied for user ''@'localhost' to database,需要的朋友可以参考下
    2015-09-09
  • mysql中插入表数据中文乱码问题的解决方法

    mysql中插入表数据中文乱码问题的解决方法

    mysql是我们项目中非经常常使用的数据型数据库,下面这篇文章主要给大家介绍了关于mysql中插入表数据中文乱码问题的解决方法,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧
    2018-09-09
  • MySQL在Windows上安装的详细流程

    MySQL在Windows上安装的详细流程

    MySQL 是最流行的数据库管理系统 (DBMS) 之一,它轻量、开源且易于安装和使用,因此对于那些刚开始学习和使用关系数据库的人来说是一个不错的选择, 本文主要系统介绍Windows的环境下MySQL的安装过程和验证过程,需要的朋友可以参考下
    2024-12-12
  • MySQL Hints控制查询优化器的选择问题小结

    MySQL Hints控制查询优化器的选择问题小结

    MySQL Hints是一种强大的工具,可以帮助我们解决复杂的查询性能问题,然而,它们应该谨慎使用,并且总是与彻底的测试和验证相结合,本文介绍MySQL Hints控制查询优化器的选择,感兴趣的朋友一起看看吧
    2024-06-06
  • MySQL数据实时同步Redis的方案全解析

    MySQL数据实时同步Redis的方案全解析

    Canal通过解析MySQL的binlog,实现数据增量同步到Redis,保持数据一致性,核心工作原理是Canal伪装成MySQL从库,模拟从库交互,获取并解析binlog,然后更新到Redis,该方案对业务侵入小,适用于实时数据同步场景,本文介绍MySQL数据实时同步Redis的方法,感兴趣的朋友一起看看吧
    2025-12-12
  • MySQL数据库创建新用户及授予权限的完整流程

    MySQL数据库创建新用户及授予权限的完整流程

    这篇文章主要给大家介绍了MySQL数据库创建新用户及授予权限的完整流程,通过这些步骤,管理员可以有效管理数据库用户,确保数据库的安全性和高效运行,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-11-11
  • MySql使用mysqldump 导入与导出方法总结

    MySql使用mysqldump 导入与导出方法总结

    这篇文章主要介绍了MySql使用mysqldump 导入与导出方法总结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • MySQL 的ANALYZE与 OPTIMIZE命令(最佳实践指南)

    MySQL 的ANALYZE与 OPTIMIZE命令(最佳实践指南)

    MySQL的ANALYZE TABLE更新统计信息优化查询性能,OPTIMIZE TABLE重组表结构回收空间,二者锁级别与执行时间不同,建议定期维护、备份并监控,结合工具跟踪表健康状况以保持数据库稳定运行,本文给大家介绍MySQL的ANALYZE与OPTIMIZE命令,感兴趣的朋友一起看看吧
    2025-07-07
  • Mac下安装mysql5.7.18的详细步骤

    Mac下安装mysql5.7.18的详细步骤

    这篇文章主要为大家详细介绍了]Mac下安装mysql5.7.18的详细步骤,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05

最新评论