SQL_MODE多是比較容易讓開發人員和DBA忽略的一個變量,默認爲空。SQL_MODE的設置實際上是比較冒險的一種設置,由於在這種設置下能夠容許一些非法操做,好比能夠將NULL插入NOT NULL的字段中,也能夠插入一些非法日期,如「2012-12-32」。所以在生產環境中強烈建議開發人員將這個值設爲嚴格模式,這樣有些問題能夠在數據庫的設計和開發階段就能發現,而若是在生產環境下運行數據庫後發現這類問題,那麼修改的代價將變得十分巨大。此外,正確地設置SQL_MODE還能夠作一些約束(Constraint)檢查的工做。html
對於SQL_MODE的設置,能夠在MySQL的配置文件如my.cnf和my.ini中進行,也能夠在客戶端工具中進行,而且能夠分別進行全局的設置或當前會話的設置。下面的命令能夠用來查看當前SQL_MODE的設置狀況。mysql
*************************** 1. row ***************************
@@global.sql_mode:
※ mysql> SELECT @@session.sql_mode\G; //查詢當前會話的sql_mode值(當前會話的變量值只約束本次鏈接,修改以後對本次鏈接當即生效)。
*************************** 1. row ***************************
@@session.sql_mode: NO_UNSIGNED_SUBTRACTION
能夠看到當前全局的SQL_MODE設置爲空,而當前會話的設置爲NO_UNSIGNED_SUBTRACTION。經過如下語句能夠將當前的SQL_MODE設置爲嚴格模式。sql
Query OK, 0 rows affected (0.00 sec)
嚴格模式是指將SQL_MODE變量設置爲STRICT_TRANS_TABLES或STRICT_ALL_TABLES中的至少一種。如今來看一下SQL_MODE能夠設置的選項。數據庫
- STRICT_TRANS_TABLES:在該模式下,若是一個值不能插入到一個事務表(例如表的存儲引擎爲InnoDB)中,則中斷當前的操做。不影響非事務表(例如表的存儲引擎爲MyISAM)。
- ALLOW_INVALID_DATES:該選項並不徹底對日期的合法性進行檢查,只檢查月份是否在1~12之間,日期是否在1~31之間。該模式僅對DATE和DATETIME類型有效,而對TIMESTAMP無效,由於TIMESTAMP老是要求一個合法的輸入。
- ANSI_QUOTES:默認狀況下,MySQL的關鍵詞以及表名等均可以有反引號``引發來。啓用ANSI_QUOTES後,即可以用雙引號代替反引號。固然原來的反引號依然可用。可是引起的一個反作用是:不能用雙引號來引用字符串,由於它將被 解釋爲識別符。解決方法就是使用單引號來表示字符串。示例以下:
mysql> CREATE TABLE z ( a VARCHAR(10))ENGINE=INNODB;服務器
mysql>INSERT INTO z SELECT "aaa";session
mysql> SET sql_mode='ANSI_QUOTES';函數
mysql> INSERT INTO z SELECT "aaa"; // 'aaa'是能夠的工具
ERROR 1054 (42S22): Unknown column 'aaa' in 'field list'測試
- ERROR_FOR_DIVISION_BY_ZERO:在INSERT或UPDATE過程當中,若是數據被零除(或MOD(X,0)),則產生錯誤(不然爲警告)。若是未給出該模式,那麼數據被零除時MySQL返回NULL。若是用到INSERT IGNORE或UPDATE IGNORE 中,MySQL生成被零除警告,但操做結果爲NULL。
- HIGH_NOT_PRECEDENCE NOT:操做符的優先順序是表達式。例如,NOT a BETWEEN b AND c被解釋爲NOT(a BETWEEN b AND c),在一些舊版本MySQL中, 前面的表達式被解釋爲(NOT a)BETWEEN b AND c。啓用 HIGH_NOT_PRECEDENCE SQL模式,能夠得到之前舊版本的更高優先級的結果。下面看一個例子:
mysql> SELECT 0 BETWEEN -1 AND 1\G;spa
*************************** 1. row ***************************
0 BETWEEN -1 AND 1: 10在-1到1之間,因此返回1,若是加上NOT,則返回0,過程以下:
mysql> SELECT @@sql_mode\G;
*************************** 1. row ***************************
@@sql_mode:
mysql> SELECT not 0 BETWEEN -1 AND 1\G;
*************************** 1. row ***************************
NOT 0 BETWEEN -1 AND 1: 0可是若是啓用HIGH_NOT_PRECEDENCE模式,則SELECT NOT 0 BETWEEN -1 AND 1被解釋爲SELECT(NOT 0)BETWEEN -1 AND 1,結果就徹底相反,以下所示:
mysql> SELECT NOT 0 BETWEEN -1 AND 1\G;
*************************** 1. row ***************************
NOT 0 BETWEEN -1 AND 1: 1從上述例子中還能看出,在MySQL數據庫中BETWEEN a AND b被解釋爲[a,b]。下面作兩個簡單的測試。
mysql> SELECT 1 BETWEEN -1 AND 1\G;
*************************** 1. row ***************************
1 BETWEEN -1 AND 1: 1
mysql> SELECT -1 BETWEEN -1 AND 1\G;
*************************** 1. row ***************************
-1 BETWEEN -1 AND 1: 1
- IGNORE_SPACE: 參考 http://www.javashuo.com/article/p-uekivkak-y.html
- NO_AUTO_CREATE_USER:禁止GRANT建立密碼爲空的用戶。
- NO_AUTO_VALUE_ON_ZERO:該選項影響列爲自增加的插入。在默認設置下,若是自增加字段插入了0或NULL,其實是生成了下一個自增加值。啓用此選項後,只有NULL能夠自動生成下一個序列號。此時自增加字段插入0是能夠正常插入的。
- NO_BACKSLASH_ESCAPES:反斜槓「\」做爲普通字符而非轉義符,示例以下:
mysql> SET sql_mode='';
mysql> SELECT '\\'\G;
*************************** 1. row ***************************
\: \ [一個鍵一個值]
mysql> SET sql_mode='NO_BACKSLASH_ESCAPES';
mysql> SET '\\'\G;
*************************** 1. row ***************************
\\: \\
- NO_DIR_IN_CREATE:在建立表時忽視全部INDEX DIRECTORY和DATA DIRECTORY的選項。
- NO_ENGINE_SUBSTITUTION:若是須要的存儲引擎被禁用或未編譯,那麼拋出錯誤。默認用默認的存儲引擎替代,並拋出一個異常。
- NO_UNSIGNED_SUBTRACTION:以前已經介紹過,啓用這個選項後兩個UNSIGNED類型相減返回SIGNED類型。
- NO_ZERO_DATE:在非嚴格模式下,能夠插入形如「0000-00-00 00:00:00」的非法日期,MySQL數據庫僅拋出一個警告。而啓用該選項後,MySQL數據庫不容許插入零日期,插入零日期會拋出錯誤而非警告。
- NO_ZERO_IN_DATE:在嚴格模式下,不容許日期和月份爲零。如「2011-00-01」和「2011-01-00」這樣的格式是不容許的。採用日期或月份爲零的格式時MySQL都會直接拋出錯誤而非警告,示例以下:
mysql> SET sql_mode='NO_ZERO_IN_DATE';
mysql> CREATE TABLE a ( a DATETIME );
mysql> INSERT INTO a SELECT '2011-01-00';
ERROR 1292 (22007): Incorrect datetime value: '2011-01-00' for column 'a' at row 1
ONLY_FULL_GROUP_BY:對於GROUP BY聚合操做,若是在SELECT中的列,沒有在GROUP BY中出現,那麼這個SQL是不合法的,由於列不在GROUP BY從句中,因此對於設置了這個mode的數據庫,在使用group by 的時候,就要用MAX(),SUM(),ANT_VALUE()這種聚合函數,才能完成GROUP BY 的聚合操做。。示例以下:
mysql> SET sql_mode='ONLY_FULL_GROUP_BY';
mysql> SELECT a,SUM(b) FROM t GROUP BY b;
ERROR 1055 (42000): 'test.t.a' isn't in GROUP BY
- PAD_CHAR_TO_FULL_LENGTH:對於CHAR類型字段,不要截斷空洞數據。空洞數據就是自動填充值爲0x20的數據。先來看MySQL數據庫在默認狀況下的表現。
mysql> CREATE TABLE t ( a CHAR(10) );
mysql> INSERT INTO t SELECT 'a';
mysql>SELECT a,CHAR_LENGTH(a),HEX(a) FROM t\G;
*************************** 1. row ***************************
a: a
CHAR_LENGTH(a): 1
HEX(a): 61
1 row in set (0.04 sec)能夠看到,在默認狀況下,雖然a列是CHAR類型,可是返回的長度是1,這是由於MySQL數據庫已經對後面的空洞數據進行了截斷。若啓用PAD_CHAR_TO_FULL_LENGTH選項,則反映的是實際存儲的內容,例如:
mysql> SELECT a,CHAR_LENGTH(a),HEX(a) FROM t\G;
*************************** 1. row ***************************
a: a
CHAR_LENGTH(a): 10
HEX(a): 61202020202020202020
1 row in set (0.00 sec)能夠看到在CHAR列a中實際存儲的值爲0x61202020202020202020。
- PIPES_AS_CONCAT:將「||」視爲字符串的鏈接操做符而非或運算符,這和Oracle數據庫是同樣的,也和字符串的拼接函數Concat相相似,例如:
mysql> SET sql_mode='pipes_as_concat';
mysql> SELECT 'a'||'b'||'c'\G;
*************************** 1. row ***************************
'a'||'b'||'c': abc
1 row in set (0.00 sec)
- REAL_AS_FLOAT:將REAL視爲FLOAT的同義詞,而不是DOUBLE的同義詞。
- STRICT_ALL_TABLES:對全部引擎的表都啓用嚴格模式。(STRICT_TRANS_TABLES只對支持事務的表啓用嚴格模式)。
在嚴格模式下,一旦任何操做的數據產生問題,都會終止當前的操做。對於啓用STRICT_ALL_TABLES選項的非事務引擎來講,這時數據可能停留在一個未知的狀態。這可能不是全部非事務引擎願意看到的一種狀況,所以須要很是當心這個選項可能帶來的潛在影響。
下面的幾種SQL_MODE設置是以前討論的幾種選項的組合。
- ANSI:等同於REAL_AS_FLOAT、PIPES_AS_CONCAT和ANSI_QUOTES、IGNORE_SPACE的組合。
- ORACLE:等同於PIPES_AS_CONCAT、 ANSI_QUOTES、IGNORE_SPACE、 NO_KEY_OPTIONS、 NO_TABLE_OPTIONS、 NO_FIELD_OPTIONS和NO_AUTO_CREATE_USER的組合。
- TRADITIONAL:等同於STRICT_TRANS_TABLES、 STRICT_ALL_TABLES、NO_ZERO_IN_DATE、NO_ZERO_DATE、 ERROR_FOR_DIVISION_BY_ZERO、NO_AUTO_CREATE_USER和 NO_ENGINE_SUBSTITUTION的組合。
- MSSQL:等同於PIPES_AS_CONCAT、 ANSI_QUOTES、 IGNORE_SPACE、NO_KEY_OPTIONS、NO_TABLE_OPTIONS和 NO_FIELD_OPTIONS的組合。
- DB2:等同於PIPES_AS_CONCAT、ANSI_QUOTES、 IGNORE_SPACE、NO_KEY_OPTIONS、 NO_TABLE_OPTIONS和NO_FIELD_OPTIONS的組合。
- MYSQL323:等同於NO_FIELD_OPTIONS和HIGH_NOT_PRECEDENCE的組合。
- MYSQL40:等同於NO_FIELD_OPTIONS和HIGH_NOT_PRECEDENCE的組合。
- MAXDB:等同於PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE、NO_KEY_OPTIONS、 NO_TABLE_OPTIONS、 NO_FIELD_OPTIONS和 NO_AUTO_CREATE_USER的組合。