背景:在以前的升級過程當中,爲了對RD更加友好的支持,咱們都是把MySQL的SQL MODE修改爲低版本的,可是這樣每每也會帶來一些其餘問題,今天咱們就來梳理一下,SQL MODE在MySQL 5.6和5.7兩個版本之間的差別,讓DBA在後續的升級過程當中,更加從容。html
# MySQL 5.6 Default SQL_MODE; mysql> select @@sql_mode; +--------------------------------------------+ | @@sql_mode | +--------------------------------------------+ | NO_ENGINE_SUBSTITUTION | +--------------------------------------------+ 1 row in set (0.00 sec) # MySQL 5.7 Default SQL_MODE; mysql> select @@sql_mode; +-------------------------------------------------------------------------------------------------------------------------------------------+ | @@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,NO_ENGINE_SUBSTITUTION | +-------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)
在select、having、group by列表裏引用的列必須在group by列表中,不然報錯。mysql
嚴格模式控制MySQL如何處理非法或丟失的輸入值的SQL。有幾種緣由可使一個值爲非法。例如,數據類型錯誤或超出範圍。當新插入的行不包含某列的沒有顯示定義DEFAULT子句的值,則該值被丟失。sql
對於事務表,當啓用STRICT_ALL_TABLES或STRICT_TRANS_TABLES模式時,若是語句中有非法或丟失值,則會出現錯誤。SQL語句被回滾。ui
對於非事務表,STRICT_TRANS_TABLES,MySQL將非法值轉換爲最接近該列的合法值並插入調整後的值。若是值丟失,MySQL在列中插入隱式 默認值。在任何狀況下,MySQL都會生成警告而不是給出錯誤並繼續執行語句。this
若是你不使用嚴格模式(即不啓用STRICT_TRANS_TABLES或STRICT_ALL_TABLES模式),對於非法或丟失的值,MySQL將插入調整後的值並給出警告。在嚴格模式,你能夠經過INSERT IGNORE或UPDATE IGNORE來實現。spa
在嚴格模式,不接受月或日部分爲0的日期,對年不限制。若是使用IGNORE選項,咱們爲相似的日期插入’0000-00-00’。在非嚴格模式,能夠接受該日期,但會生成警告。code
在嚴格模式,不要將’0000-00-00’作爲合法日期。你仍然能夠用IGNORE選項插入零日期。在非嚴格模式,能夠接受該日期,但會生成警告。orm
在嚴格模式,在INSERT或UPDATE過程當中,若是被零除(或MOD(X,0)),則產生錯誤(不然爲警告)。若是未給出該模式,被零除時MySQL返回NULL。若是用到INSERT IGNORE或UPDATE IGNORE中,MySQL生成被零除警告,但操做結果爲NULL。htm
在嚴格模式下,防止GRANT自動建立新用戶,除非還指定了密碼。blog
mysql> select @@sql_mode; +-------------------------------------------+ | @@sql_mode | +-------------------------------------------+ | ONLY_FULL_GROUP_BY,NO_ENGINE_SUBSTITUTION | +-------------------------------------------+ 1 row in set (0.00 sec) mysql> select * from words group by id; ERROR 1055 (42000): 'tom.words.word' isn't in GROUP BY mysql> select id,count(word) from words group by word; ERROR 1055 (42000): 'tom.words.id' isn't in GROUP BY mysql> select id,word,count(word) from words group by word; ERROR 1055 (42000): 'tom.words.id' isn't in GROUP BY mysql> select word,count(word) from words group by word having count(word)>1; +------+-------------+ | word | count(word) | +------+-------------+ | bbbb | 3 | +------+-------------+ 1 row in set (0.00 sec) mysql> select * from words; +----+------+ | id | word | +----+------+ | 1 | aaaa | | 2 | bbbb | | 3 | cccc | | 4 | bbbb | | 5 | bbbb | +----+------+ 5 rows in set (0.00 sec)
mysql> CREATE TABLE `test` (`time` datetime NOT NULL DEFAULT '1111-00-01 00:00:00' ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; Query OK, 0 rows affected (0.00 sec) mysql> select @@sql_mode; +-------------------------------------------+ | @@sql_mode | +-------------------------------------------+ | ONLY_FULL_GROUP_BY,NO_ENGINE_SUBSTITUTION | +-------------------------------------------+ 1 row in set (0.00 sec) mysql> set sql_mode='ONLY_FULL_GROUP_BY,NO_ENGINE_SUBSTITUTION,NO_ZERO_IN_DATE,NO_ZERO_DATE'; Query OK, 0 rows affected, 2 warnings (0.00 sec) mysql> drop table test; Query OK, 0 rows affected (0.00 sec) mysql> CREATE TABLE `test` (`time` datetime NOT NULL DEFAULT '1111-00-01 00:00:00' ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; Query OK, 0 rows affected, 1 warning (0.01 sec) mysql> select @@sql_mode; +------------------------------------------------------------------------+ | @@sql_mode | +------------------------------------------------------------------------+ | ONLY_FULL_GROUP_BY,NO_ZERO_IN_DATE,NO_ZERO_DATE,NO_ENGINE_SUBSTITUTION | +------------------------------------------------------------------------+ 1 row in set (0.00 sec) mysql> select @@version; +------------+ | @@version | +------------+ | 5.6.35-log | +------------+ 1 row in set (0.00 sec) mysql> set 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,NO_ENGINE_SUBSTITUTION'; Query OK, 0 rows affected, 3 warnings (0.00 sec) mysql> drop table test; Query OK, 0 rows affected (0.00 sec) mysql> CREATE TABLE `test` (`time` datetime NOT NULL DEFAULT '1111-00-01 00:00:00' ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; ERROR 1067 (42000): Invalid default value for 'time'
下面的例子:
# 不合法默認值; CREATE TABLE `test` (`time` datetime NOT NULL DEFAULT '1111-00-01 00:00:00' ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; # 合法默認值; CREATE TABLE `test` (`time` datetime NOT NULL DEFAULT '1111-01-01 00:00:00' ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; # 合法默認值; CREATE TABLE `test` (`time` datetime NOT NULL DEFAULT '0000-01-01 00:00:00' ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
mysql> select @@sql_mode; +------------------------+ | @@sql_mode | +------------------------+ | NO_ENGINE_SUBSTITUTION | +------------------------+ 1 row in set (0.00 sec) mysql> set 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,NO_ENGINE_SUBSTITUTION'; Query OK, 0 rows affected, 3 warnings (0.00 sec) mysql> use tom Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> show create table words; +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | words | CREATE TABLE `words` ( `id` int(11) NOT NULL AUTO_INCREMENT, `word` varchar(4) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 | +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) mysql> insert into words(word) values("abcde"); ERROR 1406 (22001): Data too long for column 'word' at row 1 mysql> insert into words(word) values(10/0); ERROR 1365 (22012): Division by 0 mysql> insert into words(word) values(13); Query OK, 1 row affected (0.00 sec) mysql> insert into words(id) values(abc); ERROR 1054 (42S22): Unknown column 'abc' in 'field list' mysql> insert into words(id) values('abc'); ERROR 1366 (HY000): Incorrect integer value: 'abc' for column 'id' at row 1 mysql> alter table words change `word` `word` varchar(3) DEFAULT NULL; ERROR 1265 (01000): Data truncated for column 'word' at row 1 mysql> alter table words change `id` `id` int(10) unsigned NOT NULL AUTO_INCREMENT; Query OK, 7 rows affected (0.01 sec) Records: 7 Duplicates: 0 Warnings: 0 mysql> insert into words(id) values(-1); ERROR 1264 (22003): Out of range value for column 'id' at row 1 mysql>show create table words1; +--------+---------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +--------+---------------------------------------------------------------------------------------------------------------------------------------------------------+ | words1 | CREATE TABLE `words1` ( `id` int(11) NOT NULL AUTO_INCREMENT, `word` varchar(5) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 | +--------+---------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) mysql> insert into words1(id) values(1); ERROR 1364 (HY000): Field 'word' doesn't have a default value
##表數據以下 mysql> select * from words; +----+------+ | id | word | +----+------+ | 7 | aaaa | | 8 | bbbb | | 9 | cccc | | 10 | bbbb | | 11 | cccc | +----+------+ 5 rows in set (0.00 sec) ##5.6環境執行 mysql> select * from (select * from words order by id desc) a group by word ; +----+------+ | id | word | +----+------+ | 7 | aaaa | | 10 | bbbb | | 11 | cccc | +----+------+ 3 rows in set (0.00 sec) ##5.7環境執行 mysql> select * from (select * from words order by id desc) a group by word ; +----+------+ | id | word | +----+------+ | 7 | aaaa | | 8 | bbbb | | 9 | cccc | +----+------+ 3 rows in set (0.00 sec) ##正確的姿式 mysql> select max(id),word from (select * from words order by id desc) a group by word ; +---------+------+ | max(id) | word | +---------+------+ | 7 | aaaa | | 10 | bbbb | | 11 | cccc | +---------+------+ 3 rows in set (0.00 sec)
官方鏈接:點我查看