SQL模式介紹
MySQL服務(wù)器可以在不同的SQL操作模式,并能應(yīng)用這些模式不同的客戶问顷,根據(jù)不同的價(jià)值SQL模式系統(tǒng) 變量校摩。數(shù)據(jù)庫(kù)管理員可以設(shè)置全局SQL模式相匹配的網(wǎng)站服務(wù)器操作要求,每個(gè)應(yīng)用程序可以設(shè)置會(huì)話 SQL模式自身的要求朱巨。
SQL模式定義MySQL應(yīng)支持哪些SQL語(yǔ)法,以及應(yīng)執(zhí)行哪種數(shù)據(jù)驗(yàn)證檢查枉长。這樣可以更容易地在不同的環(huán)境中使用MySQL冀续,并結(jié)合其它數(shù)據(jù)庫(kù)服務(wù)器使用MySQL。
介紹各SQL模式
ONLY_FULL_GROUP_BY
在嚴(yán)格模式下必峰,不要讓GROUP BY部分中的查詢指向未選擇的列洪唐,否則報(bào)錯(cuò)。
NO_ZERO_DATE
在嚴(yán)格模式吼蚁,不要將’0000-00-00’做為合法日期凭需。你仍然可以用IGNORE選項(xiàng)插入零日期。在非嚴(yán)格模式肝匆,可以接受該日期粒蜈,但會(huì)生成警告。
NO_ZERO_IN_DATE
在嚴(yán)格模式旗国,不接受月或日部分為0的日期(也就是說(shuō)比NO_ZERO_DATE)枯怖,對(duì)年不限制。如果使用IGNORE選項(xiàng)能曾,我們?yōu)轭愃频娜掌诓迦搿?000-00-00’度硝。在非嚴(yán)格模式肿轨,可以接受該日期,但會(huì)生成警告蕊程。
ERROR_FOR_DIVISION_BY_ZERO
在嚴(yán)格模式椒袍,在INSERT或UPDATE過(guò)程中,如果被零除(或MOD(X藻茂,0))驹暑,則產(chǎn)生錯(cuò)誤(否則為警告)。如果未給出該模式辨赐,被零除時(shí)MySQL返回NULL岗钩。如果用到INSERT IGNORE或UPDATE IGNORE中,MySQL生成被零除警告肖油,但操作結(jié)果為NULL。
NO_AUTO_CREATE_USER
在嚴(yán)格模式下臂港,防止GRANT自動(dòng)創(chuàng)建新用戶森枪,除非還指定了密碼。
NO_ENGINE_SUBSTITUTION
如果需要的存儲(chǔ)引擎被禁用或未編譯审孽,可以防止自動(dòng)替換存儲(chǔ)引擎县袱。
STRICT_TRANS_TABLES
為事務(wù)存儲(chǔ)引擎啟用嚴(yán)格模式,也可能為非事務(wù)存儲(chǔ)引擎啟用嚴(yán)格模式佑力,非法數(shù)據(jù)值被拒絕式散,下面有詳細(xì)說(shuō)明。
嚴(yán)格模式控制MySQL如何處理非法或丟失的輸入值打颤。有幾種原因可以使一個(gè)值為非法暴拄。例如,數(shù)據(jù)類型錯(cuò)誤编饺,不適合列乖篷,或超出范圍。當(dāng)新插入的行不包含某列的沒(méi)有顯示定義DEFAULT子句的值透且,則該值被丟失撕蔼。
對(duì)于事務(wù)表瑰妄,當(dāng)啟用STRICT_ALL_TABLES或STRICT_TRANS_TABLES模式時(shí)吆视,如果語(yǔ)句中有非法或丟失值,則會(huì)出現(xiàn)錯(cuò)誤澳盐。語(yǔ)句被放棄并滾動(dòng)锅论。
對(duì)于非事務(wù)表讼溺,如果插入或更新的第1行出現(xiàn)壞值,兩種模式的行為相同最易。語(yǔ)句被放棄肾胯,表保持不變竖席。如果語(yǔ)句插入或修改多行,并且壞值出現(xiàn)在第2或后面的行敬肚,結(jié)果取決于啟用了哪個(gè)嚴(yán)格選項(xiàng):
對(duì)于STRICT_ALL_TABLES毕荐,MySQL返回錯(cuò)誤并忽視剩余的行。但是艳馒,在這種情況下憎亚,前面的行已經(jīng)被插入或更新。這說(shuō)明你可以部分更新弄慰,這可能不是你想要的第美。要避免這點(diǎn),最好使用單行語(yǔ)句陆爽,因?yàn)檫@樣可以不更改表即可以放棄什往。
對(duì)于STRICT_TRANS_TABLES,MySQL將非法值轉(zhuǎn)換為最接近該列的合法值并插入調(diào)整后的值慌闭。如果值丟失别威,MySQL在列中插入隱式 默認(rèn)值。在任何情況下驴剔,MySQL都會(huì)生成警告而不是給出錯(cuò)誤并繼續(xù)執(zhí)行語(yǔ)句省古。
嚴(yán)格模式不允許非法日期,例如’2004-04-31’丧失。它不允許禁止日期使用“零”部分豺妓,例如’2004-04-00’或”零”日期。要想禁止布讹,應(yīng)在嚴(yán)格模式基礎(chǔ)上琳拭,啟用NO_ZERO_IN_DATE和NO_ZERO_DATE SQL模式。
如果你不使用嚴(yán)格模式(即不啟用STRICT_TRANS_TABLES或STRICT_ALL_TABLES模式)描验,對(duì)于非法或丟失的值臀栈,MySQL將插入調(diào)整后的值并給出警告。在嚴(yán)格模式挠乳,你可以通過(guò)INSERT IGNORE或UPDATE IGNORE來(lái)實(shí)現(xiàn)权薯。
ANSI
更改語(yǔ)法和行為,使其更符合標(biāo)準(zhǔn)SQL睡扬。
TRADITIONAL
Make MySQL的行為象“傳統(tǒng)”SQL數(shù)據(jù)庫(kù)系統(tǒng)盟蚣。該模式的簡(jiǎn)單描述是當(dāng)在列中插入不正確的值時(shí)“給出錯(cuò)誤而不是警告”。注釋:一旦發(fā)現(xiàn)錯(cuò)誤立即放棄INSERT/UPDATE卖怜。如果你使用非事務(wù)存儲(chǔ)引擎屎开,這種方式不是你想要的,因?yàn)槌霈F(xiàn)錯(cuò)誤前進(jìn)行的數(shù)據(jù)更改不會(huì)“滾動(dòng)”马靠,結(jié)果是更新“只進(jìn)行了一部分”奄抽。
ALLOW_INVALID_DATES
在嚴(yán)格模式下不要檢查全部日期蔼两。只檢查1到12之間的月份和1到31之間的日。這在Web應(yīng)用程序中逞度,當(dāng)你從三個(gè)不同的字段獲取年额划、月、日档泽,并且想要確切保存用戶插入的內(nèi)容(不進(jìn)行日期驗(yàn)證)時(shí)很重要俊戳。該模式適用于DATE和DATETIME列。不適合TIMESTAMP列馆匿,TIMESTAMP列需要驗(yàn)證日期抑胎。
啟用嚴(yán)格模式后,服務(wù)器需要合法的月和日渐北,不僅僅是分別在1到12和1到31范圍內(nèi)阿逃。例如,禁用嚴(yán)格模式時(shí)’2004-04-31’是合法的赃蛛,但啟用嚴(yán)格模式后是非法的恃锉。要想在嚴(yán)格模式允許遮掩固定日期,還應(yīng)啟用ALLOW_INVALID_DATES焊虏。
ANSI_QUOTES
將‘”‘視為識(shí)別符引號(hào)(‘`’引號(hào)字符),不要視為字符串的引號(hào)字符秕磷。在ANSI模式诵闭,你可以仍然使用‘`’來(lái)引用識(shí)別符。啟用ANSI_QUOTES后澎嚣,你不能用雙引號(hào)來(lái)引用字符串疏尿,因?yàn)樗唤忉尀樽R(shí)別符。
ERROR_FOR_DIVISION_BY_ZERO
在嚴(yán)格模式易桃,在INSERT或UPDATE過(guò)程中褥琐,如果被零除(或MOD(X,0))晤郑,則產(chǎn)生錯(cuò)誤(否則為警告)敌呈。如果未給出該模式,被零除時(shí)MySQL返回NULL造寝。如果用到INSERT IGNORE或UPDATE IGNORE中磕洪,MySQL生成被零除警告,但操作結(jié)果為NULL诫龙。
HIGH_NOT_PRECEDENCE
NOT操作符的優(yōu)先順序是表達(dá)式例如NOT a BETWEEN b AND c被解釋為NOT (a BETWEEN b AND c)析显。在一些舊版本MySQL中, 表達(dá)式被解釋為(NOT a) BETWEEN b AND c签赃。啟用HIGH_NOT_PRECEDENCESQL模式谷异,可以獲得以前的更高優(yōu)先級(jí)的結(jié)果分尸。
IGNORE_SPACE
允許函數(shù)名和‘(‘之間有空格。強(qiáng)制將所有函數(shù)名視為保存的字歹嘹。結(jié)果是箩绍,如果你想要訪問(wèn)保存為字的數(shù)據(jù)庫(kù)、表或列名荞下,你必須引用它伶选。例如,因?yàn)橛蠻SER()函數(shù)尖昏,mysql數(shù)據(jù)庫(kù)中的user表名和該表內(nèi)的User列被保存下來(lái)仰税,因此你必須引用它們.
NO_AUTO_VALUE_ON_ZERO
NO_AUTO_VALUE_ON_ZERO影響AUTO_INCREMENT列的處理。一般情況抽诉,你可以向該列插入NULL或0生成下一個(gè)序列號(hào)陨簇。NO_AUTO_VALUE_ON_ZERO禁用0,因此只有NULL可以生成下一個(gè)序列號(hào)迹淌。
如果將0保存到表的AUTO_INCREMENT列河绽,該模式會(huì)很有用。(不推薦采用該慣例)唉窃。例如耙饰,如果你用mysqldump轉(zhuǎn)儲(chǔ)表并重載,MySQL遇到0值一般會(huì)生成新的序列號(hào)纹份,生成的表的內(nèi)容與轉(zhuǎn)儲(chǔ)的表不同苟跪。重載轉(zhuǎn)儲(chǔ)文件前啟用NO_AUTO_VALUE_ON_ZERO可以解決該問(wèn)題。mysqldump在輸出中自動(dòng)包括啟用NO_AUTO_VALUE_ON_ZERO的語(yǔ)句蔓涧。
NO_BACKSLASH_ESCAPES
禁用反斜線字符(‘\’)做為字符串內(nèi)的退出字符件已。啟用該模式,反斜線則成為普通字符元暴。
NO_DIR_IN_CREATE
創(chuàng)建表時(shí)篷扩,忽視所有INDEX DIRECTORY和DATA DIRECTORY指令。該選項(xiàng)對(duì)從復(fù)制服務(wù)器有用茉盏。
NO_ENGINE_SUBSTITUTION
如果需要的存儲(chǔ)引擎被禁用或未編譯鉴未,可以防止自動(dòng)替換存儲(chǔ)引擎。
NO_FIELD_OPTIONS
不要在SHOW CREATE TABLE的輸出中打印MySQL專用列選項(xiàng)鸠姨。該模式在可移植模式(portability mode)下用于mysqldump歼狼。
NO_KEY_OPTIONS
不要在SHOW CREATE TABLE的輸出中打印MySQL專用索引選項(xiàng)。該模式在可移植模式(portability mode)下用于mysqldump享怀。
NO_TABLE_OPTIONS
不要在SHOW CREATE TABLE的輸出中打印MySQL專用表選項(xiàng)(例如ENGINE)羽峰。該模式在可移植模式(portability mode)下用于mysqldump。
NO_UNSIGNED_SUBTRACTION
在減運(yùn)算中,如果某個(gè)操作數(shù)沒(méi)有符號(hào)梅屉,不要將結(jié)果標(biāo)記為UNSIGNED值纱。請(qǐng)注意這樣使UNSIGNED BIGINT不能100%用于上下文中。參見(jiàn)12.8節(jié)坯汤,“Cast函數(shù)和操作符”虐唠。
PIPES_AS_CONCAT
將||視為字符串連接操作符(+)(同CONCAT()),而不視為OR惰聂。
REAL_AS_FLOAT
將REAL視為FLOAT的同義詞疆偿,而不是DOUBLE的同義詞。
SQL模式測(cè)試
一搓幌、查看當(dāng)前SQL模式
來(lái)看一下MySQL 5.6&5.7的默認(rèn)SQL模式
# MySQL 5.6 Default SQL_MODE;
mysql> select @@sql_mode;
+--------------------------------------------+
| @@sql_mode???????????????????????????????? |
+--------------------------------------------+
| STRICT_TRANS_TABLES,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)
MySQL 5.7對(duì)數(shù)據(jù)的嚴(yán)謹(jǐn)性和一致性上比之前版本要提升很多
二杆故、指定模式
你可以在配置文件中用:
1sql_mode = "modes"
選項(xiàng)啟動(dòng)mysqld來(lái)設(shè)置默認(rèn)SQL模式,modes是用逗號(hào)(‘,’)間隔開(kāi)的一系列不同的模式溉愁。如果你想要重設(shè)处铛,該值還可以為空(sql-mode =””)。
你還可以動(dòng)態(tài)改變SQL模式:
1SET [SESSION|GLOBAL] sql_mode='modes'
設(shè)置GLOBAL變量時(shí)需要擁有SUPER權(quán)限拐揭,并且會(huì)影響從那時(shí)起連接的所有客戶端的操作撤蟆。設(shè)置SESSION變量只影響當(dāng)前的客戶端。任何客戶端可以隨時(shí)更改自己的會(huì)話sql_mode值堂污。
三家肯、示例演示
1.在嚴(yán)格的模式下
mysql> create table tbl_kenyon(id int null,vname varchar(6));
Query OK, 0 rows affected (0.12 sec)
mysql> insert into tbl_kenyon values(1,'123456');
Query OK, 1 row affected (0.00 sec)
mysql> insert into tbl_kenyon values(1,'1234567');
ERROR 1406 (22001): Data too long for column 'vname' at row 1
mysql> insert into tbl_kenyon values('','123456');
ERROR 1366 (HY000): Incorrect integer value: '' for column 'id' at row 1
mysql> insert into tbl_kenyon values(null,'123456');
Query OK, 1 row affected (0.01 sec)
2.在非嚴(yán)格的模式下
mysql> set @@sql_mode='';
Query OK, 0 rows affected (0.00 sec)
mysql> insert into tbl_kenyon values(99,'123456');
Query OK, 1 row affected (0.00 sec)
mysql> insert into tbl_kenyon values(1,'1234567');
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> insert into tbl_kenyon values('','123456');
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> show warnings;
+---------+------+------------------------------------------------------+
| Level | Code | Message |
+---------+------+------------------------------------------------------+
| Warning | 1366 | Incorrect integer value: '' for column 'id' at row 1 |
+---------+------+------------------------------------------------------+
1 row in set (0.00 sec)
四、 應(yīng)用場(chǎng)景
兩種模式各有利弊盟猖,通常生產(chǎn)上會(huì)設(shè)置嚴(yán)格模式讨衣,可以保證數(shù)據(jù)的完整性。非嚴(yán)格模式并不一定就是差的扒披,在數(shù)據(jù)一致性要求不嚴(yán)的場(chǎng)景下某些忽略警告操作可能更方便值依,比如不同版本數(shù)據(jù)庫(kù)的非關(guān)鍵數(shù)據(jù)導(dǎo)入:
mysql> load data infile '/data/source_data/trace/tbl_msg.sql' into table tbl_msg;
ERROR 1366 (HY000): Incorrect integer value: 'NULL' for column 'pid' at row 1
換個(gè)模式導(dǎo)入:
mysql> set @@session.sql_mode='';
Query OK, 0 rows affected (0.00 sec)
mysql> load data infile '/data/source_data/trace/ tbl_msg.sql' into table tbl_msg;
Query OK, 23525 rows affected, 65535 warnings (2.80 sec)
Records: 23525 Deleted: 0 Skipped: 0 Warnings: 185707
轉(zhuǎn)自:http://www.ywnds.com/?p=7049