mysql的sql_mode模式

最近将测试环境的MySQL从5.0升级到了5.5,然后升级之后同事说有些insert SQL执行不了,一开始还以为是MySQL版本的问题,

后来查了下发现MySQL是因为MySQL有个sql mode设置,所以查看了下2个MySQL的sql mode设置,发现果然不一样

果然是不一样的呢,那就学习下MySQL的sql mode吧。

mysql5.0以上版本支持三种sql_mode模式:ANSI、TRADITIONAL和STRICT_TRANS_TABLES。
ANSI模式:宽松模式,对插入数据进行校验,如果不符合定义类型或长度,对数据类型调整或截断保存,报warning警告。

TRADITIONAL模式:严格模式,当向mysql数据库插入数据时,进行数据的严格校验,保证错误数据不能插入,报error错误。用于事物时,会进行事物的回滚。

STRICT_TRANS_TABLES模式:严格模式,进行数据的严格校验,错误数据不能插入,报error错误。

首先我们设置ANSI模式.

mysql> show variables like 'sql_mode';+---------------+--------------------------------------------+

| Variable_name | Value                                      |

+---------------+--------------------------------------------+

| sql_mode      | STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION |

+---------------+--------------------------------------------+

1 row in set (0.00 sec)

 mysql> set @@sql_mode=ANSI;

 Query OK, 0 rows affected (0.00 sec)



 mysql> show variables like 'sql_mode';

 +---------------+-------------------------------------------------------------+

 | Variable_name | Value                                                       |

 +---------------+-------------------------------------------------------------+

 | sql_mode      | REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ANSI |

 +---------------+-------------------------------------------------------------+

 1 row in set (0.00 sec)

这是设置之后的sql_mode.然后我们建立表格插入数据.

mysql> create table tt(name varchar(4), pass varchar(4));

Query OK, 0 rows affected (0.09 sec)



mysql> 

mysql> insert into tt values('aaaaa','aaaaa'),('bbbb','bbbb');

Query OK, 2 rows affected, 2 warnings (0.00 sec)

Records: 2  Duplicates: 0  Warnings: 2



mysql> show warnings;

+---------+------+-------------------------------------------+

| Level   | Code | Message                                   |

+---------+------+-------------------------------------------+

| Warning | 1265 | Data truncated for column 'name' at row 1 |

| Warning | 1265 | Data truncated for column 'pass' at row 1 |

+---------+------+-------------------------------------------+

2 rows in set (0.00 sec)

mysql> select * from tt;

+------+------+

| name | pass |

+------+------+

| aaaa | aaaa |

| bbbb | bbbb |

+------+------+

2 rows in set (0.00 sec)

这时候发现数据可以插入成功,只是产生了2条waring数据,数据也被截取过了。

上面的是插入对应相同列的数据,我们再试下只插入一列数据的情况

mysql> insert into tt(name) values('eeee'),('2eeee');

Query OK, 2 rows affected, 1 warning (0.01 sec)

Records: 2  Duplicates: 0  Warnings: 1

mysql> show warnings;

+---------+------+-------------------------------------------+

| Level   | Code | Message                                   |

+---------+------+-------------------------------------------+

| Warning | 1265 | Data truncated for column 'name' at row 2 |

+---------+------+-------------------------------------------+

1 row in set (0.00 sec)

mysql> select * from tt;

+------+------+

| name | pass |

+------+------+

| aaaa | aaaa |

| bbbb | bbbb |

| eeee | NULL |

| 2eee | NULL |

+------+------+

4 rows in set (0.00 sec)

如果我们只设置了第一列name的value,而且另外一个列pass并没有设置为allow null的情况下,数据也是可以插入成功的。但是也有2条warning,而且数据也是被截取过的。

那接下来我们设置STRICT_TRANS_TABLES模式:

mysql> set @@sql_mode=STRICT_TRANS_TABLES;

Query OK, 0 rows affected (0.00 sec)



mysql> show variables like 'sql_mode';

+---------------+---------------------+

| Variable_name | Value               |

+---------------+---------------------+

| sql_mode      | STRICT_TRANS_TABLES |

+---------------+---------------------+

1 row in set (0.00 sec)

重复我们刚刚插入数据的方式

mysql> insert into tt values('aaaaa','aaaaa'),('bbbb','bbbb');

ERROR 1406 (22001): Data too long for column 'name' at row 1

发现SQL直接报错了,提示数据太长而不能插入.

修改数据插入

mysql> insert into test values('aaaa','aaaa'),('bbbbb','bbbbb');

ERROR 1406 (22001): Data too long for column 'name' at row 2
mysql> select * from test;

+------+------+

| name | pass |

+------+------+

| aaaa | aaaa |

| bbbb | bbbb |

| eeee | NULL |

| 2eee | NULL |

+------+------+

4 rows in set (0.00 sec)

发现数据都是插入不成功的。那我们再试试刚刚只插入1列数据的情况呢

mysql> insert test(name) value('wmq');

Query OK, 1 row affected (0.03 sec)



mysql> select * from test;

+------+------+-------+

| name | pass | value |

+------+------+-------+

| test |      |       |

| wmq  |      |       |

+------+------+-------+

2 rows in set (0.00 sec)

也是可以插入成功的,所以我可以自动,sql mode跟字段是否匹配没有关系。但是我们查看table info的create SQL可以发现,有的MySQL客户端

在建立表的时候,会给字段默认加上defalut '' 这个值,例如:

CREATE TABLE `test1` (

  `name` varchar(4) NOT NULL

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `test2` (

  `name` varchar(4) NOT NULL DEFAULT '',

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

这是在我客户端和我同事的客户端上建表的create语句。有的客户端会让你选择default custom 有的会显示无默认值。但是我电脑的客户端就没有让你选择

default ''的这个选项。

这点以后一定要非常注意,最好是统一使用相同的MySQL客户端或者干脆禁用远程账户,统一使用PMA或者命令行,这里有点偏题了

最后我们设置TRADITIONAL:

mysql> set @@sql_mode = 'TRADITIONAL';

Query OK, 0 rows affected (0.00 sec)



mysql> show variables like 'sql_mode';

+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------+

| Variable_name | Value                                                                                                                                                |

+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------+

| sql_mode      | STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |

+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------+

1 row in set (0.00 sec)

发现和STRICT_TRANS_TABLES一样

 

你可能感兴趣的:(mysql)