5.7 默認模式:
ONLY_FULL_GROUP_BY, STRICT_TRANS_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE,
ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER, NO_ENGINE_SUBSTITUTION,
5.7.4 廢棄:ERROR_FOR_DIVISION_BY_ZERO
5.7.5 默認:ONLY_FULL_GROUP_BY , STRICT_TRANS_TABLES
5.7.7 默認:NO_AUTO_CREATE_USER
5.7.8 默認:ERROR_FOR_DIVISION_BY_ZERO, NO_ZERO_DATE, NO_ZERO_IN_DATE
命令行啓動服務設置:
配置文件中的設置: sql-mode="modes"
對於多個的模式用逗號隔開。清除模式則設置爲空字符:
sql-mode=""
在服務運行時改變模式,有全局和會話級別:
SET GLOBAL sql_mode = 'modes';
SET SESSION sql_mode = 'modes';
全局模式在線設置需要超級權限(SUPER),新的連接纔會生效;會話級別模式每個客戶端都可設置。
查看當前模式:
SELECT @@GLOBAL.sql_mode;
SELECT @@SESSION.sql_mode;
SELECT @@sql_mode;
在未了解各種模式的影響下,表分區後建議不要再變更模式,同步複製的實例也建議模式保持一致。
======================================================================
【ANSI】
等價於 REAL_AS_FLOAT, PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE. ONLY_FULL_GROUP_BY(MySQL 5.7.5)
======================================================================
REAL_AS_FLOAT :REAL 爲 FLOAT 的同義詞(默認情況, REAL 爲 DOUBLE 的同義詞).
PIPES_AS_CONCAT : 管道符(||) 作爲連接符.(默認使用函數 CONCAT 連接字符)
ANSI_QUOTES :標準引號, 雙引號不作爲字符串引號,作爲關鍵字標識符引號
IGNORE_SPACE :對於內置函數與其他字符間的空格,忽略空格
【ANSI_QUOTES】
create table max(id int);
create table max (id int);
create table `max`(id int);
create table 'max'(id int);
create table "max"(id int);
create table "max"(id int);
SELECT "AAA";
SELECT "AAA";
【IGNORE_SPACE】
create table max(id int);
create table max (id int);
create table max (id int);
【PIPES_AS_CONCAT】
SET sql_mode='PIPES_AS_CONCAT';
select 'aa' || 'bb';
select CONCAT('aa' , 'bb');
======================================================================
【STRICT_TRANS_TABLES】
對事務型表操作,插入表時如果第一行數據不符合約束則終止執行並回滾。
======================================================================
create table test(value int(1));
SET sql_mode='';
insert into test(value) values('a'),(1),(2147483647);
insert into test(value) values(1),('a'),(2147483647);
select * from test;
+
| value |
+
| 1 |
| 0 |
| 2147483647 |
+
drop table test;
create table test(value int(1));
SET sql_mode='STRICT_TRANS_TABLES';
insert into test(value) values('a'),(1),(2147483647);
insert into test(value) values(1),('a'),(2147483647);
======================================================================
【TRADITIONAL】
======================================================================
MySQL 5.7.4 以前版本 和 MySQL 5.7.8 及以上版本:
STRICT_TRANS_TABLES, STRICT_ALL_TABLES, NO_AUTO_CREATE_USER
, NO_ENGINE_SUBSTITUTION,NO_ZERO_IN_DATE, NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO.
MySQL 5.7.4 至 5.7.7 版本:
STRICT_TRANS_TABLES, STRICT_ALL_TABLES, NO_AUTO_CREATE_USER, NO_ENGINE_SUBSTITUTION.
(STRICT_ALL_TABLES / STRICT_TRANS_TABLES 包含 NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO)
【STRICT_ALL_TABLES】
包括: ERROR_FOR_DIVISION_BY_ZERO, NO_ZERO_DATE, NO_ZERO_IN_DATE
【NO_AUTO_CREATE_USER】禁止使用 GRANT 創建密碼爲空的用戶。
標準寫法:
create user user01@'localhost' identified by 'user01';
grant all on test.* to user01@'localhost';
flush privileges;
SET sql_mode='';
grant all on test.* to user01@'localhost';
SET sql_mode='NO_AUTO_CREATE_USER';
#報錯 ERROR 1133 (42000): Can't find any matching row in the user table
grant all on test.* to user02@'localhost';
#正確,需要設置密碼
grant all on test.* to user02@'localhost' identified by 'user02';
------------------------------
【NO_ENGINE_SUBSTITUTION】
默認情況創建或修改表的存儲引擎不支持時,自動轉爲默認的INNODB;
使用該模式後,存儲引擎不支持時則報錯。
------------------------------
#查看所有存儲引擎
show engines;
SET sql_mode='';
create table test(id int) ENGINE=FEDERATED;
select table_name,engine from information_schema.tables where table_schema='test' and table_name='test';
+
| table_name | engine |
+
| test | InnoDB |
+
SET sql_mode='NO_ENGINE_SUBSTITUTION';
create table test(id int) ENGINE=FEDERATED;
直接報錯:ERROR 1286 (42000): Unknown storage engine 'FEDERATED'
【NO_ZERO_IN_DATE】日期格式(月日)是否支持'00'.
create table test(value date);
SET sql_mode='';
insert into test(value) values('2018-00-00');
SET sql_mode='NO_ZERO_IN_DATE';
insert into test(value) values('2017-00-00');
【NO_ZERO_DATE】 不允許插入 '0000-00-00' 日期
create table test(value date);
SET sql_mode='';
insert into test(value) values('0000-00-00');
SET sql_mode='STRICT_TRANS_TABLES';
insert into test(value) values('0000-00-00');
SET sql_mode='NO_ZERO_DATE';
insert into test(value) values('0000-00-00');
SET sql_mode='NO_ZERO_DATE,STRICT_TRANS_TABLES';
insert into test(value) values('0000-00-00');
【ERROR_FOR_DIVISION_BY_ZERO】 0爲除數時報錯
create table test(value int);
SET sql_mode='';
select 10/0;
insert into test(value) values(10/0);
SET sql_mode='STRICT_TRANS_TABLES';
select 10/0;
insert into test(value) values(10/0);
SET sql_mode='ERROR_FOR_DIVISION_BY_ZERO';
select 10/0;
insert into test(value) values(10/0);
SET sql_mode='ERROR_FOR_DIVISION_BY_ZERO,STRICT_TRANS_TABLES';
select 10/0;
insert into test(value) values(10/0);
======================================================================
【ALLOW_INVALID_DATES】
檢查日期格式合法性(DATE 或 DATETIME, 非 TIMESTAMP )
======================================================================
create table test(createdate date,name varchar(10));
SET sql_mode='';
select @@sql_mode;
insert into test values ('2018-02-32','a');
insert into test values ('2018-13-01','b');
select * from test;
+
| createdate | name |
+
| 0000-00-00 | a |
| 0000-00-00 | b |
+
SET sql_mode='ALLOW_INVALID_DATES';
select @@sql_mode;
insert into test values ('2018-02-32','d');
insert into test values ('2018-13-01','e');
select * from test;
+
| createdate | name |
+
| 0000-00-00 | a |
| 0000-00-00 | b |
| 0000-00-00 | d |
| 0000-00-00 | e |
+
SET sql_mode='ALLOW_INVALID_DATES,STRICT_TRANS_TABLES';
insert into test values ('2018-02-32','f');
ERROR 1292 (22007): Incorrect date value: '2018-02-32' for column 'createdate' at row
SET sql_mode='STRICT_TRANS_TABLES';
insert into test values ('2018-02-32','g');
ERROR 1292 (22007): Incorrect date value: '2018-02-32' for column 'createdate' at row 1
insert into test values ('0000-00-00','h');
======================================================================
【NO_AUTO_VALUE_ON_ZERO】
運行序列中插入 "0",如果 id 不約束唯一, 可插入多個。插入 NULL 值默認都會自增。
======================================================================
create table test(id int not null auto_increment,name varchar(10),key(id));
SET sql_mode='';
insert into test values (1,'a');
insert into test values (0,'b');
insert into test values (null,'c');
select * from test;
+
| id | name |
+
| 1 | a |
| 2 | b |
| 3 | c |
+
SET sql_mode='NO_AUTO_VALUE_ON_ZERO';
insert into test values (0,'d');
insert into test values (null,'e');
select * from test;
+
| id | name |
+
| 0 | d |
| 1 | a |
| 2 | b |
| 3 | c |
| 4 | e |
+
======================================================================
【HIGH_NOT_PRECEDENCE】
未使用模式 HIGH_NOT_PRECEDENCE, "not id between 2 and 4" 相當於 "not (id between 2 and 4)"
使用模式 HIGH_NOT_PRECEDENCE, "not id between 2 and 4" 相當於 "(not id) between 2 and 4".
======================================================================
create table test(id int);
insert into test values (1),(2),(3),(4),(5);
SET sql_mode='';
SELECT NOT 1 BETWEEN -5 AND 5;
select * from test where not id between 2 and 4;
select * from test where not (id between 2 and 4);
select * from test where (not id) between 2 and 4;
SET sql_mode='HIGH_NOT_PRECEDENCE';
SELECT NOT 1 BETWEEN -5 AND 5;
select * from test where not id between 2 and 4;
select * from test where not (id between 2 and 4);
select * from test where (not id) between 2 and 4;
======================================================================
【NO_BACKSLASH_ESCAPES】反斜槓"\"爲普通字符而不是轉義字符。
======================================================================
SET sql_mode='';
select '\\';
SET sql_mode='NO_BACKSLASH_ESCAPES';
select '\\';
======================================================================
【NO_UNSIGNED_SUBTRACTION】
UNSIGNED 類型如果得到一個負值,則報錯。(儘量不要 UNSIGNED)
======================================================================
SET sql_mode='';
select cast(0 as unsigned) - 1;
錯誤:ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(cast(0 as unsigned) - 1)'
SET sql_mode='NO_UNSIGNED_SUBTRACTION';
select cast(0 as unsigned) - 1;
+
| cast(0 as unsigned) - 1 |
+
| -1 |
+
======================================================================
【ONLY_FULL_GROUP_BY】
聚合語句安裝標準寫法,如 oracle sqlserver 一樣。
======================================================================
create table test(name varchar(10),value int);
insert into test values ('a',45),('a',42),('b',85),('c',65),('c',39);
SET sql_mode='';
select * from test group by name;
select value,sum(value) from test group by name;
SET sql_mode='ONLY_FULL_GROUP_BY';
select name,sum(value) from test group by name;
======================================================================
【PAD_CHAR_TO_FULL_LENGTH】
對於 char、nchar 類型,默認以空字符填充,查詢時自動去掉空字符。
啓用該模式後,查詢時空字符保留。
======================================================================
create table test(c1 char(10),c2 nchar(10));
insert into test values ('aaa','bbb');
SET sql_mode='';
select length(c1),length(c2),char_length(c1),char_length(c2) from test;
+
| length(c1) | length(c2) | char_length(c1) | char_length(c2) |
+
| 3 | 3 | 3 | 3 |
+
SET sql_mode='PAD_CHAR_TO_FULL_LENGTH';
select length(c1),length(c2),char_length(c1),char_length(c2) from test;
+
| length(c1) | length(c2) | char_length(c1) | char_length(c2) |
+
| 10 | 10 | 10 | 10 |
+
======================================================================
【NO_DIR_IN_CREATE】
創建表分區時,忽略命令 INDEX DIRECTORY 和 DATA DIRECTORY。用於副本示例中的選項。
======================================================================
SET sql_mode='';
create table test(id int)
partition by range(id)(
partition p0 values less than (5),
partition p1 values less than maxvalue
);
SET sql_mode='NO_DIR_IN_CREATE';
create table test(id int)
ENGINE=MyISAM
partition by range(id)(
partition p0 values less than (5)
DATA DIRECTORY = 'E:/AAA/P0/data'
INDEX DIRECTORY = 'E:/AAA/P0/idx',
partition p1 values less than maxvalue
DATA DIRECTORY = 'E:/AAA/P1/data'
INDEX DIRECTORY = 'E:/AAA/P1/idx'
);