浅谈MySQL的sql_mode

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介: 今天我们来分享一下MySQL的SQL mode , 这也是我们比较容易忽略的一点,我们在一开始安装数据库的时候其实就要先考虑要保留哪些SQL mode,去除哪些,合理的配置能够减少很多不必要的麻烦。

SQL mode


今天我们来分享一下MySQL的SQL mode , 这也是我们比较容易忽略的一点,我们在一开始安装数据库的时候其实就要先考虑要保留哪些SQL mode,去除哪些,合理的配置能够减少很多不必要的麻烦。


MySQL 5.7默认的SQL mode包含ONLY_FULL_GROUP_BY, STRICT_TRANS_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER, and NO_ENGINE_SUBSTITUTION


这是MySQL官网的原文描述:“These modes were added to the default SQL mode in MySQL 5.7: The ONLY_FULL_GROUP_BY and STRICT_TRANS_TABLES modes were added in MySQL 5.7.5. The NO_AUTO_CREATE_USER mode was added in MySQL 5.7.7. The ERROR_FOR_DIVISION_BY_ZERO, NO_ZERO_DATE, and NO_ZERO_IN_DATE modes were added in MySQL 5.7.8. For additional discussion regarding these changes to the default SQL mode value, see SQL Mode Changes in MySQL 5.7.”


show sql mode


SELECT @@GLOBAL.sql_mode;
SELECT @@SESSION.sql_mode;


set sql mode


设置为GLOBAL,那么所有的客户端都会受到影响,不过要拥有SUPER权限才能进行设置,也就是root用户,设置SESSION,那么受影响的只是当前的连接会话。


SET GLOBAL sql_mode ='ONLY_FULL_GROUP_BY'
SET SESSION sql_mode ='ONLY_FULL_GROUP_BY'


下面我们就针对默认设置的这几种SQL mode进行详细的讲解,其他的哪些大家可以去官网参考。


https://docs.oracle.com/cd/E17952_01/mysql-5.7-en/sql-mode.html


默认的SQL mode


ONLY_FULL_GROUP_BY


设置了这个值,如果使用GROUP BY,在SELECT后面出现的字段,在GROUP BY后面必须出现,不然报错如下


Expression #3 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'blue.shop.price' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by


如下使用的是MySQL默认的sql_mode


ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION


那么下面的语句就会报错,因为GROUP BY后面只有一个字段,而SELECT * 是查出所有字段,所以就报错。


SELECT * FROM shop GROUP BY article 


这样写就不会报错


SELECT * FROM shop GROUP BY article , dealer , price


不过我们不可能使用一个GROUP BY,后面还要跟着所有字段,显然不合理,那么就应该将其关闭,只需要将其去掉就行


STRICT_TRANS_TABLES


严格模式控制MySQL如何处理数据更改语句中的无效或缺失值,如INSERT或UPDATE。一个值可能因多种原因无效。例如,它可能具有列的错误数据类型,或者它可能超出了范围。如果要插入的新行不包含定义中没有显式DEFAULT子句的非null列的值,则该值缺失。


比如我们的某个字段设置不能为NULL,而我们插入的数据这个字段为NULL,那么就不能通过,就会报错如下:


1364 - Field 'dealer' doesn't have a default value


那么这个问题要怎么解决呢?我相信这个问题大家经常遇到,一般是我们在插入数据的时候实体的属性没有赋值,所以导致这个问题,所以我们会去检查代码,然后给属性赋值,另外一种做法就是去除STRICT_TRANS_TABLES,这样就不会进行校验,不过是极其不推荐这样做的,因为要我们要保证数据的完整性,所以必须在代码层面做好工作。


NO_ZERO_IN_DATE


NO_ZERO_IN_DATE模式会影响服务器是否允许年部分不为零但月或日部分为0的日期。(该模式影响日期,如“2010-00-01”或“2010-01-00”,但不影响“0000-00-00”。要控制服务器是否允许'0000-00-00',请使用NO_ZERO_DATE模式。)NO_ZERO_IN_DATE的效果还取决于是否启用严格SQL模式,如果没有启用严格SQL模式STRICT_TRANS_TABLES,那么启用了NO_ZERO_IN_DATE也没用。


如下SQL的日期月和日为0,启用了严格模式STRICT_TRANS_TABLES和NO_ZERO_IN_DATE,那么就会报错。


INSERT INTO `blue`.`shop` (`article`, `dealer` ,`price`,`date`) VALUES ('商品5', '5', 5.00, '2022-00-00');


1292 - Incorrect datetime value: '2022-00-00' for column 'date' at row 1


去除严格模式STRICT_TRANS_TABLESNO_ZERO_IN_DATE就不会报错。


NO_ZERO_DATE


上面的NO_ZERO_IN_DATE可以插入'0000-00-00',如果使用了严格模式STRICT_TRANS_TABLES和NO_ZERO_DATE,那么就不可以插入'0000-00-00'。


ERROR_FOR_DIVISION_BY_ZERO


对于INSERT或者UPDATE中,如果被除数为0,那么就会产生错误,数据无法插入,MOD(N,M)也是一样



INSERT INTO `blue`.`shop` (`article`,dealer ,`price`,`date`) VALUES ('商品5', '5', MOD(10,0), '0000-00-00');


对于SELECT,如果被除数为0,那么就会返回NULL,MOD(N,M)也一样。


SELECT price / 0  FROM shop


报错信息: 1365 - Division by 0


NO_AUTO_CREATE_USER


不能使用grant命令创建密码为空的用户。


NO_ENGINE_SUBSTITUTION


如果指定了NO_ENGINE_SUBSTITUTION,我们在创建表或者修改表的时候,如果去指定了不存在或者不支持的存储引擎,那么就会报错,无法创建和修改,如果没有配置NO_ENGINE_SUBSTITUTION,那么就会将我们指定的存储引擎(不支持或者不存在)的存储引擎替换为默认的存储引擎,MySQL5.7后的默认存储引擎为InnoDB,所以就会自动设置为InnoDB。


如下我们创建表,将存储引擎设置为一个不存在的InnoDBTest,因为我们去除了NO_ENGINE_SUBSTITUTION,所以不会报错,并且会替换成默认的InnoDB


创建sql


CREATE TABLE store ( `name` VARCHAR ( 255 ) DEFAULT NULL ) ENGINE = InnoDBTest


查看创建过程


SHOW CREATE TABLE store


结果


CREATE TABLE `store` (
  `name` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci


MySQL存储引擎


SHOW ENGINES;



关于MySQL的SQL mode,就说到这里,我只列举了MySQL5.7默认的几种并对其进行讲解,有兴趣的话可以去了解其他的选项。感谢你的观看,我们下期见!


相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
25天前
|
SQL 关系型数据库 MySQL
【MySQL实战笔记】02.一条SQL更新语句是如何执行的-1
【4月更文挑战第4天】SQL更新语句执行涉及查询和日志模块,主要为`redo log`和`binlog`。`redo log`先写日志再写磁盘,保证`crash-safe`;`binlog`记录逻辑日志,支持所有引擎,且追加写入。执行过程分为执行器查找数据、更新内存和`redo log`(prepare状态)、写入`binlog`、提交事务(`redo log`转commit)。两阶段提交确保日志逻辑一致,支持数据库恢复至任意时间点。
20 0
|
29天前
|
SQL 关系型数据库 MySQL
SQL Error (2013): Lost connection to MySQL server at 'waiting for initial communication packet', sys...
SQL Error (2013): Lost connection to MySQL server at 'waiting for initial communication packet', sys...
|
24天前
|
SQL 关系型数据库 MySQL
mysql 大小写、sql_mode
mysql 大小写、sql_mode
|
1天前
|
SQL 关系型数据库 MySQL
【MySQL系列笔记】常用SQL
常用SQL分为三种类型,分别为DDL,DML和DQL;这三种类型的SQL语句分别用于管理数据库结构、操作数据、以及查询数据,是数据库操作中最常用的语句类型。 在后面学习的多表联查中,SQL是分析业务后业务后能否实现的基础,以及后面如何书写动态SQL,以及完成级联查询的关键。
17 6
|
1天前
|
SQL 关系型数据库 MySQL
【MySQL-4】简述SQLの通用语法及4种基本语句介绍(DDL/DML/DQL/DCL)
【MySQL-4】简述SQLの通用语法及4种基本语句介绍(DDL/DML/DQL/DCL)
|
1天前
|
SQL 存储 关系型数据库
【MySQL系列笔记】SQL优化
SQL优化是通过调整数据库查询、索引、表结构和配置参数等方式,提高SQL查询性能和效率的过程。它旨在减少查询执行时间、减少系统资源消耗,从而提升数据库系统整体性能。优化方法包括索引优化、查询重写、表分区、适当选择和调整数据库引擎等。
16 3
|
3天前
|
SQL 关系型数据库 MySQL
MySQL SQL error: #1271 - Illegal mix of collations for operation ‘UNION‘
MySQL SQL error: #1271 - Illegal mix of collations for operation ‘UNION‘
|
3天前
|
SQL 关系型数据库 MySQL
【MySQL】:探秘主流关系型数据库管理系统及SQL语言
【MySQL】:探秘主流关系型数据库管理系统及SQL语言
11 0
|
4天前
|
SQL 存储 缓存
详解MySQL中一条SQL执行过程
详解MySQL中一条SQL执行过程
8 0
|
6天前
|
SQL 关系型数据库 MySQL
【MySQL】SQL优化
【MySQL】SQL优化