sql_mode是個容易被忽略的變量,在5.5預設值是空值,在這種設定下是可以允許一些非法操作的,比如允許一些非法資料的插入。
在5.6中強化了該值設置,5.7中更注重了安全規範性,這個值默認為嚴格模式
透過設定sql mode,可以完成不同嚴格程度的資料校驗,有效保障資料準備性。
透過設定sql mode 為寬鬆模式,來確保大多數sql符合標準的sql語法,這樣應用在不同資料庫之間進行遷移時,則不需要對業務sql進行較大的修改,可以很方便的遷移到目標資料庫。
ONLY_FULL_GROUP_BY
ONLY_FULL_GROUP_BY
ONLY_FULL_GROUP_BY
#對於使用GROUP BY 進行查詢的SQL,不允許SELECT 部分出現GROUP BY 中未出現的字段,也就是SELECT 查詢的字段必須是GROUP BY 中出現的或者使用聚合函數的或者是具有唯一屬性的。
create table test(name varchar(10),value int); insert into test values ('a',1),('a',20),('b',23),('c',15),('c',30); #默认情况是可能会写出无意义或错误的聚合语句: 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; -- 错误写法则报错 select value,sum(value) from test group by name; # 报错终止 ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'test.test.value' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
STRICT_TRANS_TABLES
#這個選項只對交易型儲存引擎起作用,對非交易型儲存引擎無效,其作用是啟用嚴格SQL 模式。在strict sql模式下,在INSERT或UPDATE語句中,插入或更新了某個不符合規定的欄位值,則會直接錯誤中斷動作
create table test(value int(1)); SET sql_mode=''; #默认只要第一个值 insert into test(value) values('a'),(1); #不报错 insert into test(value) values(2),('a'); #不报错 select * from test; +------------+ | value | +------------+ | 0 | | 1 | | 2 | | 0 | +------------+ #后面删除表不再说明! drop table test; create table test(value int(1)); SET sql_mode='STRICT_TRANS_TABLES'; #每个值都判断 insert into test(value) values('a'),(1); #报错,第一行'a'错误。 ERROR 1366 (HY000): Incorrect integer value: 'a' for column 'value' at row 1
#NO_ZERO_IN_DATE
MySQL中插入的時間欄位值,不允許日期和月份為零
create table test(value date); SET sql_mode=''; insert into test(value) values('2020-00-00'); #结果为 '2020-00-00' SET sql_mode='NO_ZERO_IN_DATE'; insert into test(value) values('2021-00-00'); #不符合,转为 '0000-00-00'
NO_ZERO_DATE
#MySQL中插入的時間欄位值,不允許插入‘0000-00-00’ 日期
create table test(value date); SET sql_mode=''; insert into test(value) values('0000-00-00'); #无警告 warning SET sql_mode='STRICT_TRANS_TABLES'; insert into test(value) values('0000-00-00'); #无警告 warning SET sql_mode='NO_ZERO_DATE'; insert into test(value) values('0000-00-00'); #有警告 warning SET sql_mode='NO_ZERO_DATE,STRICT_TRANS_TABLES' insert into test(value) values('0000-00-00'); # 报错终止 ERROR 1292 (22007): Incorrect date value: '0000-00-00' for column 'value' at row 1
#ERROR_FOR_DIVISION_BY_ZERO
當該選項關閉時,數字被0除,得到NULL且不會產生警告
當該選項開啟且處於非strict sql模式下,數字被0除,得到NULL但是會產生警告
當該選項開啟且處於strict sql模式下,數字被0除,產生錯誤且中斷操作
create table test(value int); SET sql_mode=''; select 10/0; #无警告 warning insert into test(value) values(10/0); #无警告 warning SET sql_mode='STRICT_TRANS_TABLES'; select 10/0; #无警告 warning insert into test(value) values(10/0); #无警告 warning SET sql_mode='ERROR_FOR_DIVISION_BY_ZERO'; select 10/0; #有警告 warning insert into test(value) values(10/0); #有警告 warning SET sql_mode='ERROR_FOR_DIVISION_BY_ZERO,STRICT_TRANS_TABLES'; select 10/0; #有警告 warning insert into test(value) values(10/0); #报错:ERROR 1365 (22012): Division by 0
禁止GRANT建立密碼為空的使用者
SET sql_mode=''; grant all on test.* to test01@'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 test01@'localhost' identified by 'test01...';## ##########NO_ENGINE_SUBSTITUTION###############在使用CREATE TABLE或ALTER TABLE語法執行儲存引擎的時候,如果設定的儲存引擎被停用或未編譯,會產生錯誤。 ###
# 查看当前支持的存储引擎 show engines; set sql_mode=''; create table test(id int) ENGINE="test"; Query OK, 0 rows affected, 2 warnings (0.03 sec) 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=test; # 报错 ERROR 1286 (42000): Unknown storage engine 'test'###三、sql_mode 設定與修改######方式一: 這是可修改全域變數###
> show variables like '%sql_mode%'; > set @@sql_mode="NO_ENGINE_SUBSTITUTION" > set session sql_mode='STRICT_TRANS_TABLES';###方式二: 透過修改設定檔(需要重新啟動生效)## #
# vim /etc/my.cnf [mysqld] ...... sql_mode="NO_ENGINE_SUBSTITUTION" ......
以上是MySQL 5.7之SQL_MODE怎麼設定的詳細內容。更多資訊請關注PHP中文網其他相關文章!