因为sql_mode设置的不同可能会出现有些SQL在一个实例可以执行,在另一个实例却不能执行。下面就记录下不同sql_mode的特点:

查看sql_mode

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

版本<=5.6.5 支持以下sql_mode

ALLOW_INVALID_DATES
ANSI_QUOTES
ERROR_FOR_DIVISION_BY_ZERO
HIGH_NOT_PRECEDENCE
IGNORE_SPACE
NO_AUTO_CREATE_USER
NO_AUTO_VALUE_ON_ZERO
NO_BACKSLASH_ESCAPES
NO_DIR_IN_CREATE
NO_ENGINE_SUBSTITUTION
NO_FIELD_OPTIONS
NO_KEY_OPTIONS
NO_TABLE_OPTIONS
NO_UNSIGNED_SUBTRACTION
NO_ZERO_DATE
NO_ZERO_IN_DATE
ONLY_FULL_GROUP_BY
PAD_CHAR_TO_FULL_LENGTH
PIPES_AS_CONCAT
REAL_AS_FLOAT
STRICT_ALL_TABLES
STRICT_TRANS_TABLES

>5.6.5

ALLOW_INVALID_DATES
ANSI_QUOTES
ERROR_FOR_DIVISION_BY_ZERO
HIGH_NOT_PRECEDENCE
IGNORE_SPACE
NO_AUTO_CREATE_USER
NO_AUTO_VALUE_ON_ZERO
NO_BACKSLASH_ESCAPES
NO_DIR_IN_CREATE
NO_ENGINE_SUBSTITUTION
NO_FIELD_OPTIONS
NO_KEY_OPTIONS
NO_TABLE_OPTIONS
NO_UNSIGNED_SUBTRACTION
NO_ZERO_DATE
NO_ZERO_IN_DATE
ONLY_FULL_GROUP_BY
PAD_CHAR_TO_FULL_LENGTH
PIPES_AS_CONCAT
REAL_AS_FLOAT
STRICT_ALL_TABLES
STRICT_TRANS_TABLES

复合sql_mode

ANSI     REAL_AS_FLOATPIPES_AS_CONCATANSI_QUOTESIGNORE_SPACE.

STRICT_TRANS_TABLES

TRADITIONAL

Equivalent to

STRICT_TRANS_TABLESSTRICT_ALL_TABLESNO_ZERO_IN_DATENO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERONO_AUTO_CREATE_USER, and NO_ENGINE_SUBSTITUTION.

ALLOW_INVALID_DATES

一般情况,月份范围是1-12,日范围是1-31,如果在mysql中插入正常范围以外的日期会怎么样呢?这取决于数据库实例设置的sql_mode。

ALLOW_INVALID_DATES 表示可以插入非法的日期,在对日期进行插入的时候不进行合法检验。但是对timestamp的合法性还是要进行检验的。

create table t_sql_mode (

id int not null primary key auto_increment, tdate date , tdatetime datetime default now(), ttimestamp timestamp default now()

) engine=innodb;

root@localhost [test]>set sql_mode='';
Query OK, 0 rows affected (0.00 sec)

root@localhost [test]>insert into t_sql_mode(tdate) values('2014-02-31');

Query OK, 1 row affected, 1 warning (0.00 sec)
root@localhost [test]>insert into t_sql_mode(tdate,tdatetime,ttimestamp) values('2014-02-31','2016-19-90 00:00:00','2016-19-90 00:00:00');
Query OK, 1 row affected, 3 warnings (0.00 sec)

root@localhost [test]>show warnings;
+---------+------+-------------------------------------------------+
| Level   | Code | Message                                         |
+---------+------+-------------------------------------------------+
| Warning | 1264 | Out of range value for column 'tdate' at row 1  |
| Warning | 1265 | Data truncated for column 'tdatetime' at row 1  |
| Warning | 1265 | Data truncated for column 'ttimestamp' at row 1 |
+---------+------+-------------------------------------------------+
3 rows in set (0.00 sec)

root@localhost [test]>select * from t_sql_mode;
+----+------------+---------------------+---------------------+
| id | tdate      | tdatetime           | ttimestamp          |
+----+------------+---------------------+---------------------+
|  2 | 0000-00-00 | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |
|  3 | 0000-00-00 | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |
+----+------------+---------------------+---------------------+

root@localhost [test]>set sql_mode='STRICT_TRANS_TABLES';
Query OK, 0 rows affected (0.00 sec)

root@localhost [test]>insert into t_sql_mode(tdate) values('2014-02-31');
ERROR 1292 (22007): Incorrect date value: '2014-02-31' for column 'tdate' at row 1

root@localhost [test]>set sql_mode='STRICT_TRANS_TABLES,ALLOW_INVALID_DATES';
Query OK, 0 rows affected, 1 warning (0.00 sec)

root@localhost [test]>insert into t_sql_mode(tdate,tdatetime,ttimestamp) values('2014-02-31','2016-19-90 00:00:00','2016-19-90 00:00:00');
ERROR 1292 (22007): Incorrect datetime value: '2016-19-90 00:00:00' for column 'tdatetime' at row 1

root@localhost [test]>insert into t_sql_mode(tdate,tdatetime,ttimestamp) values('2014-02-31','2016-09-20 00:00:00','2016-09-20 00:00:00');
Query OK, 1 row affected (0.01 sec)

root@localhost [test]>select * from t_sql_mode;
+----+------------+---------------------+---------------------+
| id | tdate      | tdatetime           | ttimestamp          |
+----+------------+---------------------+---------------------+
|  2 | 0000-00-00 | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |
|  3 | 0000-00-00 | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |
|  4 | 2014-02-31 | 2016-09-20 00:00:00 | 2016-09-20 00:00:00 |
+----+------------+---------------------+---------------------+
3 rows in set (0.00 sec)

root@localhost [test]>

mysql5.7.14 & mariadb10.0.21

如果sql_mode为空,允许插入任何数值的日期值,但是会有warning,并且将非法日期转成0000或者0000-00-00 00:00:00

如果为严格模式,且没有ALLOW_INVALID_DATES,不允许插入任何非法日期值,

如果为严格模式,且指定ALLOW_INVALID_DATES,允许插入非法的date数值,但是不允许插入非法的datetime和timestamp。

ANSI_QUOTES

这中模式下,mysql会将双引号作为标示符,类似于常用的 "`" ,不能将双引号用来引用字符串,请看例子:

root@localhost [test]>set sql_mode='';

root@localhost [test]>select `id`,`tdate` from t_sql_mode;
+----+------------+
| id | tdate      |
+----+------------+
|  2 | 0000-00-00 |
|  3 | 0000-00-00 |
|  4 | 2014-02-31 |
+----+------------+

root@localhost [test]>select "id","tdate" from t_sql_mode;
+----+-------+
| id | tdate |
+----+-------+
| id | tdate |
| id | tdate |
| id | tdate |
+----+-------+
3 rows in set (0.00 sec)

root@localhost [test]>select 'id','tdate' from t_sql_mode;
+----+-------+
| id | tdate |
+----+-------+
| id | tdate |
| id | tdate |
| id | tdate |
+----+-------+
3 rows in set (0.00 sec)

root@localhost [test]>set sql_mode='ANSI_QUOTES';
Query OK, 0 rows affected (0.00 sec)

root@localhost [test]>select `id`,`tdate` from t_sql_mode;
+----+------------+
| id | tdate      |
+----+------------+
|  2 | 0000-00-00 |
|  3 | 0000-00-00 |
|  4 | 2014-02-31 |
+----+------------+
3 rows in set (0.00 sec)

root@localhost [test]>select 'id','tdate' from t_sql_mode;
+----+-------+
| id | tdate |
+----+-------+
| id | tdate |
| id | tdate |
| id | tdate |
+----+-------+
3 rows in set (0.00 sec)

root@localhost [test]>select "id","tdate" from t_sql_mode;
+----+------------+
| id | tdate      |
+----+------------+
|  2 | 0000-00-00 |
|  3 | 0000-00-00 |
|  4 | 2014-02-31 |
+----+------------+
3 rows in set (0.00 sec)

ERROR_FOR_DIVISION_BY_ZERO

控制在除0时候的动作,

严格模式

insert,update类

select 类

严格模式|insert,update类

严格模式   ERROR_FOR_DIVISION_BY_ZERO 除0,返回null,没有warning

非严格模式,ERROR_FOR_DIVISION_BY_ZERO 除0,返回null,提示warning

严格模式,  ERROR_FOR_DIVISION_BY_ZERO 除0,会返回错误,但是如果使用了INSERT IGNORE and UPDATE IGNORE 返回null,提示warning

CREATE TABLE `division_zero` (
  `z` int(11) DEFAULT NULL
) ENGINE=InnoDB

root@localhost [test]>show variables like 'sql_mode';
+---------------+-------------------+
| Variable_name | Value             |
+---------------+-------------------+
| sql_mode      | STRICT_ALL_TABLES |
+---------------+-------------------+
1 row in set (0.00 sec)

root@localhost [test]>insert into division_zero values(1/0);
Query OK, 1 row affected (0.02 sec)

root@localhost [test]>select * from division_zero;
+------+
| z    |
+------+
| NULL |
+------+
1 row in set (0.00 sec)

root@localhost [test]>set sql_mode='ERROR_FOR_DIVISION_BY_ZERO';
Query OK, 0 rows affected, 1 warning (0.00 sec)

root@localhost [test]>insert into division_zero values(1/0);
Query OK, 1 row affected, 1 warning (0.02 sec)

root@localhost [test]>show warnings;
+---------+------+---------------+
| Level   | Code | Message       |
+---------+------+---------------+
| Warning | 1365 | Division by 0 |
+---------+------+---------------+
1 row in set (0.00 sec)

root@localhost [test]>select * from division_zero;
+------+
| z    |
+------+
| NULL |
| NULL |
+------+
2 rows in set (0.00 sec)

root@localhost [test]>set sql_mode='STRICT_ALL_TABLES,ERROR_FOR_DIVISION_BY_ZERO';
Query OK, 0 rows affected, 1 warning (0.00 sec)

root@localhost [test]>insert into division_zero values(1/0);
ERROR 1365 (22012): Division by 0
root@localhost [test]>

root@localhost [test]>insert ignore into division_zero values(1/0),(2);
Query OK, 2 rows affected, 1 warning (0.02 sec)
Records: 2  Duplicates: 0  Warnings: 1

root@localhost [test]>show warnings;
+---------+------+---------------+
| Level   | Code | Message       |
+---------+------+---------------+
| Warning | 1365 | Division by 0 |
+---------+------+---------------+
1 row in set (0.00 sec)

root@localhost [test]>select * from division_zero;
+------+
| z    |
+------+
| NULL |
| NULL |
| NULL |
|    2 |
+------+
4 rows in set (0.00 sec)

root@localhost [test]>

运行select,都会返回null,如果ERROR_FOR_DIVISION_BY_ZERO 会提示warning,没有则只返回null,没有waring。

不管是什么模式。

root@localhost [test]>set sql_mode='';
Query OK, 0 rows affected, 1 warning (0.00 sec)

root@localhost [test]>select 12/0;
+------+
| 12/0 |
+------+
| NULL |
+------+
1 row in set (0.00 sec)

root@localhost [test]>set sql_mode='STRICT_ALL_TABLES';
Query OK, 0 rows affected, 1 warning (0.00 sec)

root@localhost [test]>select 1/0;
+------+
| 1/0  |
+------+
| NULL |
+------+
1 row in set (0.00 sec)

root@localhost [test]>set sql_mode='STRICT_ALL_TABLES,ERROR_FOR_DIVISION_BY_ZERO';
Query OK, 0 rows affected, 1 warning (0.00 sec)

root@localhost [test]>select 1/0;
+------+
| 1/0  |
+------+
| NULL |
+------+
1 row in set, 1 warning (0.00 sec)

root@localhost [test]>show warnings;
+---------+------+---------------+
| Level   | Code | Message       |
+---------+------+---------------+
| Warning | 1365 | Division by 0 |
+---------+------+---------------+
1 row in set (0.00 sec)

HIGH_NOT_PRECEDENCE

控制not 运算符的优先级。

默认情况not是最后进行运算的,例如NOT a BETWEEN b AND c are parsed as NOT (a BETWEEN b AND c).但是在一些老版本中NOT a BETWEEN b AND c are parsed as (NOT a) BETWEEN b AND c).

root@localhost [test]>set sql_mode='';
Query OK, 0 rows affected (0.00 sec)

root@localhost [test]>select not 1 between -5 and 5;
+------------------------+
| not 1 between -5 and 5 |
+------------------------+
|                      0 |
+------------------------+
1 row in set (0.00 sec)

root@localhost [test]>set sql_mode='HIGH_NOT_PRECEDENCE';
Query OK, 0 rows affected (0.00 sec)

root@localhost [test]>select not 1 between -5 and 5;
+------------------------+
| not 1 between -5 and 5 |
+------------------------+
|                      1 |
+------------------------+
1 row in set (0.00 sec)

root@localhost [test]>

IGNORE_SPACE

允许函数名和'('之间有空格,这会将内建的方法和存储过程名作为保留字。这就造成,使用跟方法名一样的标示符时必须使用特殊的符号包含,比如`.

count()是内建函数,所以使用count作为表名的时候就会出错。

root@localhost [test]>set  sql_mode='IGNORE_SPACE';

root@localhost [test]>create table count ( i int);
ERROR 1064 (42000): You have an error in your SQL syntax;

root@localhost [test]>create table `count` ( i int);
Query OK, 0 rows affected (0.03 sec)
root@localhost [test]>select count (*) from test;   #这个count后面有一个空格的
+-----------+
| count (*) |
+-----------+
|         2 |
+-----------+
1 row in set (0.00 sec)

root@localhost [test]>drop table count;

root@localhost [test]>set sql_mode='';

root@localhost [test]>create table count( i int);   #这个count后面没有空格
ERROR 1064 (42000): You have an error in your SQL syntax;

root@localhost [test]>create table count ( i int); #这个count后面有空格
Query OK, 0 rows affected (0.02 sec)
root@localhost [test]>select count (*) from test;
ERROR 1064 (42000): You have an error in your SQL syntax;

root@localhost [test]>select count(*) from test;
+----------+
| count(*) |
+----------+
|        2 |
+----------+
1 row in set (0.00

NO_AUTO_CREATE_USER

不允许grant语句自动创建没有密码的账户。

5.7之后,grant不再能创建用户。

root@localhost [test]>set sql_mode='';

root@localhost [test]>grant select on test.* to 'test1'@'%';

root@localhost [test]>select user,host,authentication_string from mysql.user;
+-----------+-----------+-------------------------------------------+
| user      | host      | authentication_string                     |
+-----------+-----------+-------------------------------------------+
| root      | localhost | *E74858DB86EBA20BC33D0AECAE8A8108C56B17FA |
| mysql.sys | localhost | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE |
| root      | %         | *E74858DB86EBA20BC33D0AECAE8A8108C56B17FA |
| test      | %         | *E74858DB86EBA20BC33D0AECAE8A8108C56B17FA |
| test1     | %         |                                           |
+-----------+-----------+-------------------------------------------+

root@localhost [test]>set sql_mode='NO_AUTO_CREATE_USER';
Query OK, 0 rows affected, 1 warning (0.00 sec)

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

root@localhost [test]>select user,host,authentication_string from mysql.user;
+-----------+-----------+-------------------------------------------+
| user      | host      | authentication_string                     |
+-----------+-----------+-------------------------------------------+
| root      | localhost | *E74858DB86EBA20BC33D0AECAE8A8108C56B17FA |
| mysql.sys | localhost | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE |
| root      | %         | *E74858DB86EBA20BC33D0AECAE8A8108C56B17FA |
| test      | %         | *E74858DB86EBA20BC33D0AECAE8A8108C56B17FA |
| test1     | %         |                                           |
| test2     | %         | *E74858DB86EBA20BC33D0AECAE8A8108C56B17FA |
+-----------+-----------+-------------------------------------------+
6 rows in set (0.00 sec)

NO_AUTO_VALUE_ON_ZERO

对于自增列,插入null和0都会自增,如果就是想插入0,可以将sql_mode设置成这个模式,但是不建议插入0.因为mysqldump导出导入的时候,可能就会将0视为自自增. 可以在导入前设置NO_AUTO_VALUE_ON_ZERO。不过现在mysqldump中都会有以下信息:

开始:

/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;

结尾:

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;

create table test_autoinc (id int auto_increment primary key,score int);

root@localhost [test]>insert into test_atuoinc values(0,100);

root@localhost [test]>select * from test_autoinc;
+----+-------+
| id | score |
+----+-------+
|  1 |   100 |
+----+-------+
1 row in set (0.01 sec)

root@localhost [test]>set sql_mode='NO_AUTO_VALUE_ON_ZERO';

root@localhost [test]>insert into test_autoinc values(0,50);

root@localhost [test]>select * from test_autoinc;
+----+-------+
| id | score |
+----+-------+
|  0 |    50 |
|  1 |   100 |
+----+-------+
2 rows in set (0.00 sec)

root@localhost [test]>insert into test_autoinc values(null,80);

root@localhost [test]>select * from test_autoinc;
+----+-------+
| id | score |
+----+-------+
|  0 |    50 |
|  1 |   100 |
|  2 |    80 |

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

3 rows in set (0.00 sec)

NO_BACKSLASH_ESCAPES

在字符串中,反斜杠跟普通字符一样,没有特殊意义。

root@localhost [test]>set sql_mode='';
root@localhost [test]>select 'test\ntest';
+-----------+
| test
test |
+-----------+
| test
test |
+-----------+
1 row in set (0.00 sec)

root@localhost [test]>set sql_mode='NO_BACKSLASH_ESCAPES';

root@localhost [test]>select 'test\ntest';
+------------+
| test\ntest |
+------------+
| test\ntest |
+------------+
1 row in set (0.00 sec)

NO_DIR_IN_CREATE

忽略建表时候指定的INDEX DIRECTORY and DATA DIRECTORY。这个在主从复制中的从库比较有用。

NO_ENGINE_SUBSTITUTION

控制create table和alter table指定的引擎不可用或没有编译进的时候的表现。默认mode包含NO_ENGINE_SUBSTITUTION

禁用NO_ENGINE_SUBSTITUTION create table 的时候如果指定引擎不可用,就会使用默认引擎,并提示warning,对于alter,会提示warning,引擎不会改变。

使用NO_ENGINE_SUBSTITUTION 

如果引擎不可用,create和alter都会报错

root@localhost [test]>set sql_mode='';

root@localhost [test]>create table test_engine (i int ) engine=FEDERATED;
root@localhost [test]>show warnings;
+---------+------+-----------------------------------------------------+
| Level   | Code | Message                                             |
+---------+------+-----------------------------------------------------+
| Warning | 1286 | Unknown storage engine 'FEDERATED'                  |
| Warning | 1266 | Using storage engine InnoDB for table 'test_engine' |
+---------+------+-----------------------------------------------------+
2 rows in set (0.00 sec)

root@localhost [test]>set sql_mode='NO_ENGINE_SUBSTITUTION ';
Query OK, 0 rows affected (0.00 sec)
root@localhost [test]>create table test_engine2 (i int ) engine=FEDERATED;
ERROR 1286 (42000): Unknown storage engine 'FEDERATED'
root@localhost [test]>

NO_FIELD_OPTIONS

oracle 的sql_mode设置

Do not print MySQL-specific column options in the output of SHOW CREATE TABLE. This mode is used by mysqldump in portability mode.

NO_KEY_OPTIONS

oracle 的sql_mode设置

Do not print MySQL-specific index options in the output of SHOW CREATE TABLE. This mode is used by mysqldump in portability mode.

NO_TABLE_OPTIONS

Do not print MySQL-specific table options (such as ENGINE) in the output of SHOW CREATE TABLE. This mode is used by mysqldump in portability mode.

root@localhost [test]>set sql_mode='NO_TABLE_OPTIONS';

root@localhost [test]>show create table test\G
*************************** 1. row ***************************
       Table: test
Create Table: CREATE TABLE `test` (
  `a` int(11) NOT NULL,
  `b` int(11) DEFAULT NULL,
  PRIMARY KEY (`a`),
  UNIQUE KEY `b` (`b`)
)
1 row in set (0.00 sec)

NO_UNSIGNED_SUBTRACTION

在计算两个整数差值的时候,如果数值都是无符号数,默认结果也是无符号数,如果差值是负数,那么就会报错。

如果NO_UNSIGNED_SUBTRACTION,则允许结果是负数.

root@localhost [test]>SELECT CAST(0 AS UNSIGNED) - 1;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(cast(0 as unsigned) - 1)'
root@localhost [test]>SET sql_mode = 'NO_UNSIGNED_SUBTRACTION';
root@localhost [test]>SELECT CAST(0 AS UNSIGNED) - 1;
+-------------------------+
| CAST(0 AS UNSIGNED) - 1 |
+-------------------------+
|                      -1 |
+-------------------------+

如果是更新语句

NO_UNSIGNED_SUBTRACTION   严格模式          CAST(0 AS UNSIGNED) - 1 报错,列值不会改变

NO_UNSIGNED_SUBTRACTION   非严格模式      CAST(0 AS UNSIGNED) - 1 =0

当使用NO_UNSIGNED_SUBTRACTION的时候,不管进行计算的列类型是否是有符号还是无符号,结果都是有符号的。

root@localhost [test]>desc test_int;
+-------+------------------+------+-----+---------+-------+
| Field | Type             | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| id    | int(10) unsigned | YES  |     | NULL    |       |
+-------+------------------+------+-----+---------+-------+
1 row in set (0.00 sec)
root@localhost [test]>update test_int set id = CAST(0 AS UNSIGNED) - 1;
Query OK, 1 row affected, 1 warning (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 1
root@localhost [test]>select * from test_int;
+------+
| id   |
+------+
|    0 |
+------+
1 row in set (0.00 sec)

root@localhost [test]>set sql_mode='STRICT_ALL_TABLES,NO_UNSIGNED_SUBTRACTION';
Query OK, 0 rows affected, 1 warning (0.00 sec)
root@localhost [test]>update test_int set id = CAST(0 AS UNSIGNED) - 1;
ERROR 1264 (22003): Out of range value for column 'id' at row 1
root@localhost [test]>

mysql> SET sql_mode='';
mysql> CREATE TABLE test (c1 BIGINT UNSIGNED NOT NULL);
mysql> CREATE TABLE t1 SELECT c1 - 1 AS c2 FROM test;
mysql> DESCRIBE t1;
+-------+---------------------+------+-----+---------+-------+
| Field | Type                | Null | Key | Default | Extra |
+-------+---------------------+------+-----+---------+-------+
| c2    | bigint(21) unsigned | NO   |     | 0       |       |
+-------+---------------------+------+-----+---------+-------+mysql> SET sql_mode='NO_UNSIGNED_SUBTRACTION';
mysql> CREATE TABLE t2 SELECT c1 - 1 AS c2 FROM test;
mysql> DESCRIBE t2;
+-------+------------+------+-----+---------+-------+
| Field | Type       | Null | Key | Default | Extra |
+-------+------------+------+-----+---------+-------+
| c2    | bigint(21) | NO   |     | 0       |       |
+-------+------------+------+-----+---------+-------+

NO_ZERO_DATE

控制000-00-00是否是合法的值。跟是否是严格模式也有关系。
没有NO_ZERO_DATE,'0000-00-00' 允许插入,不会有警告
有NO_ZERO_DATE,'0000-00-00' 允许插入,有警告
严格模式,不允许插入'0000-00-00',会有报错。如果是INSERT IGNORE 或 UPDATE IGNORE,允许插入'0000-00-00' ,有警告
root@localhost [test]>set sql_mode='';
Query OK, 0 rows affected (0.00 sec)

root@localhost [test]>insert into test_date values(null,'0000-00-00');
Query OK, 1 row affected (0.01 sec)

root@localhost [test]>select * from test_date;
+----+------------+
| id | date1      |
+----+------------+
|  1 | 0000-00-00 |
+----+------------+
1 row in set (0.00 sec)

root@localhost [test]>set sql_mode='STRICT_ALL_TABLES,NO_ZERO_DATE';
Query OK, 0 rows affected, 1 warning (0.00 sec)
root@localhost [test]>insert into test_date values(null,'0000-00-00');
ERROR 1292 (22007): Incorrect date value: '0000-00-00' for column 'date1' at row 1
root@localhost [test]>

root@localhost [test]>set sql_mode='STRICT_ALL_TABLES,NO_ZERO_DATE';

root@localhost [test]>select * from test_date;
+----+------------+
| id | date1      |
+----+------------+
|  1 | 0000-00-00 |
|  2 | 0000-00-00 |
|  3 | 0000-00-00 |
+----+------------+
3 rows in set (0.00 sec)

root@localhost [test]>update ignore test_date set id = 100,date1='0000-00-00' where id = 1;
Query OK, 1 row affected, 1 warning (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 1
root@localhost [test]>show warnings;
+---------+------+------------------------------------------------+
| Level   | Code | Message                                        |
+---------+------+------------------------------------------------+
| Warning | 1264 | Out of range value for column 'date1' at row 1 |
+---------+------+------------------------------------------------+
1 row in set (0.00 sec)

root@localhost [test]>select * from test_date;
+-----+------------+
| id  | date1      |
+-----+------------+
|   2 | 0000-00-00 |
|   3 | 0000-00-00 |
| 100 | 0000-00-00 |
+-----+------------+

NO_ZERO_IN_DATE

控制有年份但是月份和日期都是0的请,例如'2010-00-01' 或 '2010-01-00', 但是没有控制'0000-00-00'. 这个由上面NO_ZERO_DATE的控制。

没有NO_ZERO_IN_DATE,可以插入2010-00-01或者2010-01-00,没有警告

有NO_ZERO_IN_DATE ,可以插入2010-00-01或者2010-01-00,有警告

严格模式,不允许插入2010-00-01或者2010-01-00,会有报错。如果是INSERT IGNORE 或 UPDATE IGNORE,允许插入,有警告

ONLY_FULL_GROUP_BY

拒绝在select,having,order by 中使用没有在group by中没有出现非聚合列。

拒绝在select,having,order by 中使用没有在group by中没有出现非聚合列。

root@localhost [test]>setsql_mode='ONLY_FULL_GROUP_BY';

root@localhost [test]>select id,name,updated_at,created_atfrom testtime where updated_at > '2016-09-13 23:06:20' group by updated_atorder by created_at;
ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause andcontains nonaggregated column 'test.testtime.id' which is not functionallydependent on columns in GROUP BY clause; this is incompatible withsql_mode=only_full_group_by
root@localhost [test]>select id,name,updated_at,created_at from testtimewhere updated_at > '2016-09-13 23:06:20' group by updated_at;
ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause andcontains nonaggregated column 'test.testtime.id' which is not functionallydependent on columns in GROUP BY clause; this is incompatible withsql_mode=only_full_group_by
root@localhost [test]>select updated_at,created_at from testtime whereupdated_at > '2016-09-13 23:06:20' group by updated_at;
ERROR 1055 (42000): Expression #2 of SELECT list is not in GROUP BY clause andcontains nonaggregated column 'test.testtime.created_at' which is notfunctionally dependent on columns in GROUP BY clause; this is incompatible withsql_mode=only_full_group_by
root@localhost [test]>select updated_at from testtime where updated_at >'2016-09-13 23:06:20' group by updated_at;
+---------------------+
| updated_at          |
+---------------------+
| 2016-09-13 23:06:21 |
| 2016-09-13 23:06:24 |
| 2016-09-13 23:53:49 |
| 2016-09-13 23:53:50 |
| 2016-09-13 23:53:51 |
+---------------------+

root@localhost [test]>set sql_mode='';
Query OK, 0 rows affected (0.00 sec)

root@localhost [test]>select id,name,updated_at,created_at from testtimewhere updated_at > '2016-09-13 23:06:20' group by updated_at order bycreated_at;
+----+------+---------------------+---------------------+
| id | name | updated_at          | created_at         |
+----+------+---------------------+---------------------+
|  3 | name | 2016-09-13 23:06:21 | 2016-09-13 23:06:21 |
|  5 | name | 2016-09-13 23:06:24 | 2016-09-13 23:06:24 |
|  6 | name | 2016-09-13 23:53:49 | 2016-09-13 23:53:49 |
|  7 | name | 2016-09-13 23:53:50 | 2016-09-13 23:53:50 |
|  9 | name | 2016-09-13 23:53:51 | 2016-09-13 23:53:51 |
+----+------+---------------------+---------------------+
5 rows in set (0.00 sec)

root@localhost [test]>

PAD_CHAR_TO_FULL_LENGTH

默认情况会将char之后的空格过滤掉,使用这个模式不会过滤char中用来补齐的空格。

root@localhost [test]>desc test_char;
+-------+----------+------+-----+----------------------+----------------+
| Field | Type     | Null | Key | Default             | Extra          |
+-------+----------+------+-----+----------------------+----------------+
| id    | int(11)  | NO   | PRI | NULL                | auto_increment |
| name  | char(20) | YES  |     | name                |               |
+-------+----------+------+-----+----------------------+----------------+

root@localhost [test]>set sql_mode='';
Query OK, 0 rows affected (0.00 sec)

root@localhost [test]>select id,name,char_length(name),length(name) fromtest_char;
+----+------+-------------------+--------------+
| id | name | char_length(name) | length(name) |
+----+------+-------------------+--------------+
|  1 | name |                 4 |           4 |
+----+------+-------------------+--------------+
1 row in set (0.00 sec)

root@localhost [test]>set sql_mode='PAD_CHAR_TO_FULL_LENGTH';
Query OK, 0 rows affected (0.00 sec)

root@localhost [test]>select id,name,char_length(name),length(name) fromtest_char;
+----+----------------------+-------------------+--------------+
| id | name                 |char_length(name) | length(name) |
+----+----------------------+-------------------+--------------+
|  1 | name                 |               20 |          20 |
+----+----------------------+-------------------+--------------+
1 row in set (0.00 sec)

PIPES_AS_CONCAT

将||作为连接字符串操作,跟concat类似,而不是or操作。

root@localhost [test]>set sql_mode='';
Query OK, 0 rows affected (0.00 sec)

root@localhost [test]>select 1||2;
+------+
| 1||2 |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

root@localhost [test]>set sql_mode='PIPES_AS_CONCAT';
Query OK, 0 rows affected (0.00 sec)

root@localhost [test]>select 1||2;
+------+
| 1||2 |
+------+
| 12   |
+------+
1 row in set (0.00 sec)

REAL_AS_FLOAT

默认real代表double,可以通过REAL_AS_FLOAT让real代表float.  real有实数的意思

root@localhost [test]>set sql_mode='';
Query OK, 0 rows affected, 1 warning (0.00 sec)

root@localhost [test]>create table test_real ( id int,score real);
Query OK, 0 rows affected (0.05 sec)

root@localhost [test]>desc test_real;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | YES  |     | NULL    |      |
| score | double  | YES  |     | NULL    |      |
+-------+---------+------+-----+---------+-------+
2 rows in set (0.00 sec)

root@localhost [test]>alter table test_real modifyscore real;
Query OK, 0 rows affected (0.03 sec)
Records: 0  Duplicates: 0  Warnings: 0

root@localhost [test]>set sql_mode='REAL_AS_FLOAT';
root@localhost [test]>desc test_real;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | YES  |     | NULL    |      |
| score | float   | YES  |     | NULL    |      |
+-------+---------+------+-----+---------+-------+
2 rows in set (0.00 sec)

STRICT_ALL_TABLES

所有的表都是严格模式,包括ERROR_FOR_DIVISION_BY_ZERO, NO_ZERO_DATE, NO_ZERO_IN_DATE

STRICT_TRANS_TABLES

所有支持事务的引擎都是严格模式,包括:ERROR_FOR_DIVISION_BY_ZERO, NO_ZERO_DATE, NO_ZERO_IN_DATE

严格模式:

严格模式控制在非法数值插入或者在使用insert和update进行数据更改时数据丢失的情况下的结果。非法数据有各种情况,比如数据类型不对,或超出类型范围。

一个没有指定默认值的列,在进行没有值插入的时候就会有数据丢失,(对于null列,如果没有值,就会插入null),严格模式还会影响create table等。

如果不是严格模式,mysql会对插入非法数据或丢失数据情况提出警告。在严格模式下就会报错,不过可以通过insert ignore和update ignore代替。

对于select语句,非法值只会有警告,不会报错。

如果不是严格模式,在尝试创建超过key长度的key时,只会提示警告,然后自动保留到最大值。

复合模式:

为了在指定模式的时候更加方便,mysql提供了一些模式的组合。

ANSI:

REAL_AS_FLOAT, PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, and (as of MySQL 5.7.5) ONLY_FULL_GROUP_BY.

DB2:

PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIELD_OPTIONS.

MSSQL

PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIELD_OPTIONS.

MYSQL323

MYSQL323, HIGH_NOT_PRECEDENCE.

MYSQL40

MYSQL40, HIGH_NOT_PRECEDENCE.

ORACLE

PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIELD_OPTIONS, NO_AUTO_CREATE_USER.

POSTGRESQL

PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIELD_OPTIONS.

TRADITIONAL

BeforeMySQL 5.7.4, and in MySQL 5.7.8 and later, TRADITIONAL is equivalent to STRICT_TRANS_TABLES, STRICT_ALL_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER, andNO_ENGINE_SUBSTITUTION.

FromMySQL 5.7.4 though 5.7.7, TRADITIONAL is equivalent to STRICT_TRANS_TABLES, STRICT_ALL_TABLES, NO_AUTO_CREATE_USER, and NO_ENGINE_SUBSTITUTION. The NO_ZERO_IN_DATE, NO_ZERO_DATE, andERROR_FOR_DIVISION_BY_ZERO modes are not named because inthose versions their effects are included in the effects of strict SQL mode (STRICT_ALL_TABLES or STRICT_TRANS_TABLES). Thus, the effects of TRADITIONAL are the same in all MySQL 5.7versions (and the same as in MySQL 5.6).

MySQL sql_mode设置相关推荐

  1. 创建mysql的表怎么显示00_Mysql sql_mode设置 timestamp default 0000-00-00 00:00:00 创建表失败处理...

    往数据库里创建新表的时候报错: [Err] 1067 - Invalid default value for 'updateTime' DROP TABLE IF EXISTS `passwd_res ...

  2. SQL_MODE设置

    1.1.   SQL_MODE设置 在生产环境中强烈建议将这个值设置为严格模式,这样有些问题可以在数据库的设计和开发阶段就能实现,而如果在生产环境下运行数据库后发现这类问题,那么修改的代价将变得十分巨 ...

  3. 【转】MySQL sql_mode 说明(及处理一起 sql_mode 引发的问题)

    1. MySQL 莫名变成了 Strict SQL Mode 最近测试组那边反应数据库部分写入失败,app层提示是插入成功,但表里面里面没有产生数据,而两个写入操作的另外一个表有数据.因为 inser ...

  4. mysql java safe model_被 MySQL sql_mode 深深伤害( 中 )

    前一章节我们讲解了 MySQL sql_mode 的一些概要的知识,讲解了使用 select @@sql_mode; 语句可以查看当前 MySQL 连接的 sql_mode 但因为篇幅有限制,我们还没 ...

  5. mysql java safe model_被 MySQL sql_mode 深深伤害( 下 )

    当我们要重新设置 MySQL sql_mode 的时候,可能看到那一串长长的列表就会患头痛病,这哪个是哪个啊,哪个是重要的啊?哪个是可以缺少的啊? 我们就会想要呼唤一个简单的版本,要是有三个特殊的 s ...

  6. mysql sql_mode 详解_五、被 MySQL sql_mode 深深伤害( 下 )

    当我们要重新设置 MySQL sql_mode 的时候,可能看到那一串长长的列表就会患头痛病,这哪个是哪个啊,哪个是重要的啊?哪个是可以缺少的啊? 我们就会想要呼唤一个简单的版本,要是有三个特殊的 s ...

  7. MySql中设置时区为东八区

    在mysqld下新增配置  default-time-zone = '+8:00' 然后重启mysql服务:windows下管理员身份启动cmd ,net stop mysql :  net star ...

  8. mysql关于时间的面试题,mysql时间设置默认值MySQL常见面试题

    1.limit(选出10 到20 条) select * from students order by id limit 9,10; 2.MySQL 会使用索引的操作符号 =,>,=,betwe ...

  9. Mysql中设置默认时间为当前值

    1.直接在创建表时添加该列并声明默认值,如下: CREATE TABLE `table1` (`id` int(11) NOT NULL,`createtime` timestamp NULL def ...

最新文章

  1. 网站HTML删除数据库中数据语句,如何以编程方式删除WebSQL中的数据库?
  2. 数字货币 如何验证Electron Cash钱包 软件来源的可靠性
  3. maven项目创建过慢解决
  4. jeecg-framework-3.3.2-RELEASE 最新版本发布
  5. android Launcher——数据加载与变更
  6. 域名型通配符ssl证书_西部数码使用指南:申请了主域名SSL证书,是否还需要申请www域名的...
  7. struts validator 基本知识 之 【出现错误信息的条数】。
  8. element ui 表格拆分表格_python拆分表格数据
  9. gg修改器修改数值没有用怎么办_gg修改器怎么用教学 gg修改器修改游戏方法介绍...
  10. 《产品游戏化》电子书下载(epub+mobi+pdf) Netflix、迪士尼、微软巨头在使用的产品策略
  11. MP3音频编解码芯片 VS1053B-L
  12. 给所有男人和女人的人生忠告
  13. MIPI介绍(CSI DSI接口)
  14. TCHAR和string的转换
  15. P1719 最大加权矩形(最大连续子段和+矩形二维降一维+前缀和)
  16. 学会这招,走哪都管用-如何在MacBook air上安装windows10环境下的所有系统
  17. 小学计算机ps课题计划,小学生学习习惯养成课题总结
  18. 97年黑客设计大赛中冠军作品
  19. JavaScript(JS) string.italics( )
  20. python开发可以用idea吗_IntelliJ IDEA 开发Python配置

热门文章

  1. 云计算系列知识点——云计算基础
  2. 在央企当程序员是一种怎样的体验?
  3. Java中:byte转换为int ,int转换为long
  4. 2023子比主题美化插件
  5. 关于双击.py文件闪退的问题
  6. CentOS7安装宝塔面板
  7. Pgsql中数组字段当作查询条件和输出数组
  8. L0、L1与L2范数、核范数
  9. 把所阅读的文章背景/主题变成白色
  10. 《PMBOK 7》-概述