前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL sql_mode应该如何指定

MySQL sql_mode应该如何指定

作者头像
MySQL轻松学
发布2019-08-08 14:56:03
2K0
发布2019-08-08 14:56:03
举报
文章被收录于专栏:MYSQL轻松学MYSQL轻松学

sql_mode是个很容易被忽视的变量,在5.6之前默认为空值,在这种设置下是可以允许一些非法操作的,比如允许一些非法数据的插入。在生产环境一般将这个值设置为严格模式。

sql_mode分类及各值定义

分类

sql_mode

说明

启用

不启用

数据检查类

NO_ENGINE_SUBSTITUTION

指定ENGINE时,需要的存储引擎被禁用或不存在,该如何处理

直接报错

Warning转成默认存储引擎

STRICT_TRANS_TABLES

INSERT、UPDATE出现少值或无效值该如何处理

直接报错

Warning超限类型值被截断非空约束允许空

NO_ZERO_DATE

在严格模式,认为日期'0000-00-00'非法

-

-

NO_ZERO_IN_DATE

-

-

ERROR_FOR_DIVISION_BY_ZERO

在严格模式,在INSERT或UPDATE过程中,如果被零除(或MOD(X,0)),则产生错误

-

-

SQL语法支持类

ONLY_FULL_GROUP_BY

对于GROUP BY聚合操作,如果在SELECT中的列、HAVING或者ORDER BY子句的列,没有在GROUP BY中出现,那么这个SQL是不合法的

直接报错

允许

ANSI_QUOTES

启用ANSI_QUOTES 后,不能用双引号来引用字符串,因为它被解释为识别符,作用与 ` 一样

直接报错

允许

PIPES_AS_CONCAT

将||视为字符串的连接操作符而非 或 运算符

-

-

NO_TABLE_OPTIONS

使用SHOW CREATE TABLE时不会输出MySQL特有的语法部分,如 ENGINE。

-

-

NO_AUTO_CREATE_USER

GRANT语法不能创建用户,除非还指定了密码。

直接报错

允许

两种组合模式:

ANSI

REAL_AS_FLOATPIPES_AS_CONCATANSI_QUOTESIGNORE_SPACEANSI

宽松模式,对插入数据进行校验,如果不符合定义类型或长度,对数据类型调整或截断保存,报warning警告。

TRADITIONAL

STRICT_TRANS_TABLESSTRICT_ALL_TABLESNO_ZERO_IN_DATENO_ZERO_DATEERROR_FOR_DIVISION_BY_ZEROTRADITIONALNO_AUTO_CREATE_USERNO_ENGINE_SUBSTITUTION

严格模式,当向mysql数据库插入数据时,进行数据的严格校验,保证错误数据不能插入,报error错误。用于事物时,会进行事物的回滚。日期类型中的月和日部分不能包含0,不能有0这样的日期(0000-00-00),数据不能除0,禁止grant自动创建新用户等一些校验。

一、测试sql_mode=''

代码语言:javascript
复制
(root@localhost) [(none)]>select @@sql_mode;
+------------+
| @@sql_mode |
+------------+
|            |
+------------+

1. 测试创建不存在的表引擎

代码语言:javascript
复制
(root@localhost) [test]>CREATE TABLE `test_4` (
    ->   `id` int(11) DEFAULT NULL,
    ->   `name` varchar(20) DEFAULT NULL,
    ->   `addr` varchar(10) DEFAULT NULL,
    ->   `sex` varchar(2) DEFAULT NULL
    -> ) ENGINE=ssssss DEFAULT CHARSET=utf8;
Query OK, 0 rows affected, 2 warnings (0.00 sec)

可以创建成功,但是有warning,不存在ssssss存储引擎,采用默认InnoDB引擎。

代码语言:javascript
复制
(root@localhost) [test]>show warnings;
+---------+------+------------------------------------------------+
| Level   | Code | Message                                        |
+---------+------+------------------------------------------------+
| Warning | 1286 | Unknown storage engine 'ssssss'        |
| Warning | 1266 | Using storage engine InnoDB for table 'test_4' |
+---------+------+------------------------------------------------+

查看表结构,存储引擎为innodb引擎。

代码语言:javascript
复制
(root@localhost) [test]>show create table test_4\G
*************************** 1. row ***************************
       Table: test_4
Create Table: CREATE TABLE `test_4` (
`id` int(11) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
`addr` varchar(10) DEFAULT NULL,
`sex` varchar(2) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

2. 测试insert值超过指定字符类型长度

代码语言:javascript
复制
(root@localhost) [test]>insert into test_4(id,name,addr,sex) values(1,'aa','aa','aaaaaaaaaa');
Query OK, 1 row affected, 1 warning (0.00 sec)

可以插入,但是有warning。

代码语言:javascript
复制
(root@localhost) [test]>show warnings;
+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message                                                                                                                                                   |
+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+
| Error | 1064 | You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'warning' at line 1 |
+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+

查看数据,超长字段值被截断。

代码语言:javascript
复制
(root@localhost) [test]>select * from test_4;
+------+------+------+------+
| id   | name | addr | sex  |
+------+------+------+------+
|    1 | aa   | aa   | aa   |
+------+------+------+------+
1 row in set (0.00 sec)

二、测试sql_mode='NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES'

1. 建表,不存在ssssss存储引擎,直接报错

代码语言:javascript
复制
(root@localhost) [test]>CREATE TABLE `test_5` (
    ->   `id` int(11) DEFAULT NULL,
    ->   `name` varchar(20) DEFAULT NULL,
    ->   `addr` varchar(10) NOT NULL,
    ->   `sex` varchar(2) DEFAULT NULL
    -> ) ENGINE=ssssss  DEFAULT CHARSET=utf8;
ERROR 1286 (42000): Unknown storage engine 'ssssss'

2.测试insert值超过字符类型长度,直接报错

代码语言:javascript
复制
(root@localhost) [test]>insert into test_4(id,name,addr,sex) values(2,'aa','aa','cccccccc');
ERROR 1406 (22001): Data too long for column 'sex' at row 1

3. 测试插入非空字段不带值,直接报错

代码语言:javascript
复制
(root@localhost) [test] >insert into test_4(id) values(6);
ERROR 1364 (HY000): Field 'addr' doesn't have a default value

三、测试sql_mode='ONLY_FULL_GROUP_BY'

代码语言:javascript
复制
(root@localhost) [test] >set @@sql_mode=ONLY_FULL_GROUP_BY;
Query OK, 0 rows affected (0.00 sec)

(root@localhost) [test] >select @@sql_mode;
+--------------------+
| @@sql_mode         |
+--------------------+
| ONLY_FULL_GROUP_BY |
+--------------------+

(root@localhost) [test] >select email from test1 group by name;
ERROR 1055 (42000): 'test.test1.email' isn't in GROUP BY

对于GROUP BY聚合操作,如果在SELECT中的列,没有在GROUP BY中出现,那么将认为这个SQL是不合法的,因为列不在GROUP BY从句中。

四、测试sql_mode='NO_AUTO_CREATE_USER'

代码语言:javascript
复制
(root@localhost) [(none)] >set sql_mode=NO_AUTO_CREATE_USER;
Query OK, 0 rows affected (0.00 sec)

(root@localhost) [(none)] >select @@sql_mode;
+---------------------+
| @@sql_mode          |
+---------------------+
| NO_AUTO_CREATE_USER |
+---------------------+
1 row in set (0.00 sec)

(root@localhost) [(none)] >grant select on test.* to 'test_user'@'%';
ERROR 1133 (42000): Can't find any matching row in the user table
(root@localhost) [(none)] >grant select on test.* to 'test_user'@'%' identified by "123456";
Query OK, 0 rows affected (0.00 sec)

grant...on操作不带密码的话会直接报错,带密码则可以创建。

五、总结

sql_mode设置哪种类型需要根据业务使用场景来定:

比如insert时,超过字段长度,业务设计不允许截断插入,而是直接失败,那么就需要指定STRICT_TRANS_TABLES模式。而有些业务则是相反,允许截断插入,则不需要指定STRICT_TRANS_TABLES模式。

一般使用模式:

sql_mode='NO_ENGINE_SUBSTITUTION'

sql_mode='NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES'

sql_mode='TRADITIONAL'

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-08-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 MYSQL轻松学 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档