mysql sql_mode

longqidong發表於2013-01-28
create table test(x varchar(4),b varchar(4))

sql_mode有三種:
一、ansi 對於不符合定義的值,會截斷到符合定義型別
mysql>set @@sql_mode=ansi
mysql> insert into test values('aaaaa','aaaaa'),('bbbb','bbbb');
Query OK, 2 rows affected, 2 warnings (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 2

mysql> show warnings;
+---------+------+-------------------------------------------+
| Level   | Code | Message                                   |
+---------+------+-------------------------------------------+
| Warning | 1265 | Data truncated for column 'name' at row 1 |
| Warning | 1265 | Data truncated for column 'pass' at row 1 |
+---------+------+-------------------------------------------+
2 rows in set (0.00 sec)

mysql> select * from test;
+------+------+
| name | pass |
+------+------+
| aaaa | aaaa |
| bbbb | bbbb |
+------+------+
2  rows in set (0.00 sec)
可以看到對於型別不匹配的,會自動截斷,並報警告


二、traditional  對於不匹配的,會報錯。如果第一條記錄就是不匹配的,則會導致同一語句中後面正常語句也不能插入,如果中間的一條記錄不匹配,則它之後的正常記錄都不會插入。
mysql>set @@sql_mode=traditional
 mysql> insert into test values('aaaaa','aaaaa'),('bbbb','bbbb');
ERROR 1406 (22001): Data too long for column 'name' at row 1
mysql> show errors;
+-------+------+------------------------------------------+
| Level | Code | Message                                  |
+-------+------+------------------------------------------+
| Error | 1406 | Data too long for column 'name' at row 1 |
+-------+------+------------------------------------------+
1 row in set (0.00 sec)

mysql> select * from test;
Empty set (0.00 sec)
上面是第一條記錄就不匹配,直接導致後面正常的額資料也不能插入。
如果不是第一條記錄出錯呢:
mysql> truncate table test;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into test values('111','111'),('aaaaa','aaaaa'),('bbbb','bbbb');
ERROR 1406 (22001): Data too long for column 'name' at row 2
mysql> select * from test;
+------+------+
| name | pass |
+------+------+
| 111  | 111  |
+------+------+
1 row in set (0.00 sec)
第一條記錄正常插入,第二條是不匹配的,導致後面的也不可用。



3.strict_trans_tables 和traditional一樣,但是有區別。
如果第一條記錄就是不匹配的,則會導致同一語句中後面正常語句也不能插入。如果中間的一條記錄不匹配,則所有記錄都能插入,不匹配的會截斷到匹配,並報警告。
mysql> set @@sql_mode=strict_trans_tables;
Query OK, 0 rows affected (0.00 sec)

mysql> 
mysql> truncate table test;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from test;
Empty set (0.00 sec)

mysql> 
mysql> insert into test values('aaaaa','aaaaa'),('bbbb','bbbb');
ERROR 1406 (22001): Data too long for column 'name' at row 1
mysql> show errors;
+-------+------+------------------------------------------+
| Level | Code | Message                                  |
+-------+------+------------------------------------------+
| Error | 1406 | Data too long for column 'name' at row 1 |
+-------+------+------------------------------------------+
1 row in set (0.00 sec)

mysql> select * from test;
Empty set (0.00 sec)

出錯的是第一條記錄,導致後面正常的也不能插入。

mysql>truncate table test;
mysql> insert into test values('111','111'),('aaaaa','aaaaa'),('bbbb','bbbb');
Query OK, 3 rows affected, 2 warnings (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 2

mysql> select * from test;
+------+------+
| name | pass |
+------+------+
| 111  | 111  |
| aaaa | aaaa |
| bbbb | bbbb |
+------+------+
3 rows in set (0.00 sec)
中間記錄報錯,所有記錄都能插入,截斷不匹配的。

上面這個表test是myisam的,所以在strict_trans_tables下,中間記錄出現錯誤,不回滾, 如果是事務表innodb,則在strict_trans_tables和traditional下都會回滾。這點需要注意:

嚴格模式控制MySQL如何處理非法或丟失的輸入值。有幾種原因可以使一個值為非法。例如,資料型別錯誤,不適合列,或超出範圍。當新插入的行不包含某列的沒有顯示定義DEFAULT子句的值,則該值被丟失。

對於事務表,當啟用STRICT_ALL_TABLES或STRICT_TRANS_TABLES模式時,如果語句中有非法或丟失值,則會出現錯誤。語句被放棄並滾動。

對於非事務表,如果插入或更新的第1行出現壞值,兩種模式的行為相同。語句被放棄,表保持不變。如果語句插入或修改多行,並且壞值出現在第2或後面的行,結果取決於啟用了哪個嚴格選項:



以下來自網上資料:

5.3.2. SQL伺服器模式

MySQL伺服器可以以不同的SQL模式來操作,並且可以為不同客戶端應用不同模式。這樣每個應用程式可以根據自己的需求來定製伺服器的操作模式。

模式定義MySQL應支援哪些SQL語法,以及應執行哪種資料驗證檢查。這樣可以更容易地在不同的環境中使用MySQL,並結合其它資料庫伺服器使用MySQL。

你可以用--sql-mode="modes"選項啟動mysqld來設定預設SQL模式。如果你想要重設,該值還可以為空(--sql-mode ="")。

你還可以在啟動後用SET [SESSION|GLOBAL] sql_mode='modes'語句設定sql_mode變數來更改SQL模式。設定 GLOBAL變數時需要擁有SUPER許可權,並且會影響從那時起連線的所有客戶端的操作。設定SESSION變數隻影響當前的客戶端。任何客戶端可以隨時更改自己的會話 sql_mode值。

Modesis是用逗號(‘,’)間隔開的一系列不同的模式。你可以用SELECT @@sql_mode語句查詢當前的模式。預設值是空(沒有設定任何模式)。

主要重要sql_mode值為:

·         ANSI

更改語法和行為,使其更符合標準SQL。

·         STRICT_TRANS_TABLES

如果不能將給定的值插入到事務表中,則放棄該語句。對於非事務表,如果值出現在單行語句或多行語句的第1行,則放棄該語句。本節後面給出了更詳細的描述。

·         TRADITIONAL

Make MySQL的行為象“傳統”SQL資料庫系統。該模式的簡單描述是當在列中插入不正確的值時“給出錯誤而不是警告”。釋:一旦發現錯誤立即放棄INSERT/UPDATE。如果你使用非事務儲存引擎,這種方式不是你想要的,因為出現錯誤前進行的資料更改不會“滾動”,結果是更新“只進行了一部分”。

本手冊指“嚴格模式”,表示至少STRICT _TRANS_TABLES或STRICT _ALL_TABLES被啟用的模式。

下面描述了支援的所有模式:

·         ALLOW_INVALID_DATES

在嚴格模式下不要檢查全部日期。只檢查1到12之間的月份和1到31之間的日。這在Web應用程式中,當你從三個不同的欄位獲取年、月、日,並且想要確切儲存使用者插入的內容(不進行日期驗證)時很重要。該模式適用於DATE和DATETIME列。不適合TIMESTAMP列,TIMESTAMP列需要驗證日期。

啟用嚴格模式後,伺服器需要合法的月和日,不僅僅是分別在1到12和1到31範圍內。例如,禁用嚴格模式時'2004-04-31'是合法的,但啟用嚴格模式後是非法的。要想在嚴格模式允許遮掩固定日期,還應啟用ALLOW_INVALID_DATES。

·         ANSI_QUOTES

將‘"’視為識別符引號(‘`’引號字元),不要視為字串的引號字元。在ANSI模式,你可以仍然使用‘`’來引用識別符。啟用ANSI_QUOTES後,你不能用雙引號來引用字串,因為它被解釋為識別符。

·         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_PRECEDENCESQL模式,可以獲得以前的更高優先順序的結果。

mysql> SET sql_mode = '';
mysql> SELECT NOT 1 BETWEEN -5 AND 5;
        -> 0
mysql> SET sql_mode = 'broken_not';
mysql> SELECT NOT 1 BETWEEN -5 AND 5;
        -> 1

·         IGNORE_SPACE

允許函式名和‘(’之間有空格。強制將所有函式名視為儲存的字。結果是,如果你想要訪問儲存為字的資料庫、表或列名,你必須引用它。例如,因為有USER()函式,mysql資料庫中的user表名和該表內的User列被儲存下來,因此你必須引用它們:

SELECT "User" FROM mysql."user";

·         NO_AUTO_CREATE_USER

防止GRANT自動建立新使用者,除非還指定了密碼。

·         NO_AUTO_VALUE_ON_ZERO

NO_AUTO_VALUE_ON_ZERO影響AUTO_INCREMENT列的處理。一般情況,你可以向該列插入NULL或0生成下一個序列號。NO_AUTO_VALUE_ON_ZERO禁用0,因此只有NULL可以生成下一個序列號。

如果將0儲存到表的AUTO_INCREMENT列,該模式會很有用。(不推薦採用該慣例)。例如,如果你用mysqldump轉儲表並過載,MySQL遇到0值一般會生成新的序列號,生成的表的內容與轉儲的表不同。過載轉儲檔案前啟用NO_AUTO_VALUE_ON_ZERO可以解決該問題。mysqldump在輸出中自動包括啟用NO_AUTO_VALUE_ON_ZERO的語句。

·         NO_BACKSLASH_ESCAPES

禁用反斜線字元(‘\’)做為字串內的退出字元。啟用該模式,反斜線則成為普通字元。

·         NO_DIR_IN_CREATE

建立表時,忽視所有INDEX DIRECTORY和DATA DIRECTORY指令。該選項對從複製伺服器有用。

·         NO_ENGINE_SUBSTITUTION

如果需要的儲存引擎被禁用或未編譯,可以防止自動替換儲存引擎。

·         NO_FIELD_OPTIONS

不要在SHOW CREATE TABLE的輸出中列印MySQL專用列選項。該模式在可移植模式(portability mode)下用於mysqldump

·         NO_KEY_OPTIONS

不要在SHOW CREATE TABLE的輸出中列印MySQL專用索引選項。該模式在可移植模式(portability mode)下用於mysqldump

·         NO_TABLE_OPTIONS

不要在SHOW CREATE TABLE的輸出中列印MySQL專用表選項(例如ENGINE)。該模式在可移植模式(portability mode)下用於mysqldump

·         NO_UNSIGNED_SUBTRACTION

在減運算中,如果某個運算元沒有符號,不要將結果標記為UNSIGNED。請注意這樣使UNSIGNED BIGINT不能100%用於上下文中。參見12.8節,“Cast函式和運算子”

 

·         NO_ZERO_DATE

在嚴格模式,不要將 '0000-00-00'做為合法日期。你仍然可以用IGNORE選項插入零日期。在非嚴格模式,可以接受該日期,但會生成警告。

·         NO_ZERO_IN_DATE

在嚴格模式,不接受月或日部分為0的日期。如果使用IGNORE選項,我們為類似的日期插入'0000-00-00'。在非嚴格模式,可以接受該日期,但會生成警告。

·         ONLY_FULL_GROUP_BY

不要讓GROUP BY部分中的查詢指向未選擇的列。

·         PIPES_AS_CONCAT

將||視為字串連線運算子(+)(同CONCAT()),而不視為OR。

·         REAL_AS_FLOAT

將REAL視為FLOAT的同義詞,而不是DOUBLE的同義詞。

·         STRICT_TRANS_TABLES

為所有儲存引擎啟用嚴格模式。非法資料值被拒絕。後面有詳細說明。

·         STRICT_TRANS_TABLES

為事務儲存引擎啟用嚴格模式,也可能為非事務儲存引擎啟用嚴格模式。後面有詳細說明。

嚴格模式控制MySQL如何處理非法或丟失的輸入值。有幾種原因可以使一個值為非法。例如,資料型別錯誤,不適合列,或超出範圍。當新插入的行不包含某列的沒有顯示定義DEFAULT子句的值,則該值被丟失。

對於事務表,當啟用STRICT_ALL_TABLES或STRICT_TRANS_TABLES模式時,如果語句中有非法或丟失值,則會出現錯誤。語句被放棄並滾動。

對於非事務表,如果插入或更新的第1行出現壞值,兩種模式的行為相同。語句被放棄,表保持不變。如果語句插入或修改多行,並且壞值出現在第2或後面的行,結果取決於啟用了哪個嚴格選項:

·         對於STRICT_ALL_TABLES,MySQL返回錯誤並忽視剩餘的行。但是,在這種情況下,前面的行已經被插入或更新。這說明你可以部分更新,這可能不是你想要的。要避免這點,最好使用單行語句,因為這樣可以不更改表即可以放棄。

·         對於STRICT_TRANS_TABLES,MySQL將非法值轉換為最接近該列的合法值並插入調整後的值。如果值丟失,MySQL在列中插入隱式 預設值。在任何情況下,MySQL都會生成警告而不是給出錯誤並繼續執行語句。13.1.5節,“CREATE TABLE語法”描述了隱式預設值。

嚴格模式不允許非法日期,例如'2004-04-31'。它不允許禁止日期使用“零”部分,例如'2004-04-00'或“”日期。要想禁止,應在嚴格模式基礎上,啟用NO_ZERO_IN_DATE和NO_ZERO_DATE SQL模式。

如果你不使用嚴格模式(即不啟用STRICT_TRANS_TABLES或STRICT_ALL_TABLES模式),對於非法或丟失的值,MySQL將插入調整後的值並給出警告。在嚴格模式,你可以透過INSERT IGNORE或UPDATE IGNORE來實現。參見13.5.4.22節,“SHOW WARNINGS語法”

下面的特殊模式快速組合了前面所列的模式。

其中包括大多數最新版本MySQL中的所有模式值。舊版本中,組合模式不包括新版本中沒有的不適用的具體模式值。

·         ANSI

等同REAL_AS_FLOAT、PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE。參見1.8.3節,“在ANSI模式下執行MySQL”

·         DB2

等同PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE、NO_KEY_OPTIONS、NO_TABLE_OPTIONS、NO_FIELD_OPTIONS。

·         MAXDB

等同PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE、NO_KEY_OPTIONS、NO_TABLE_OPTIONS、NO_FIELD_OPTIONS、NO_AUTO_CREATE_USER。

·         MSSQL

等同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。

·         ORACLE

等同PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE、NO_KEY_OPTIONS、NO_TABLE_OPTIONS、NO_FIELD_OPTIONS、NO_AUTO_CREATE_USER。

·         POSTGRESQL

等同PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE、NO_KEY_OPTIONS、NO_TABLE_OPTIONS、NO_FIELD_OPTIONS。

·         TRADITIONAL

等同STRICT_TRANS_TABLES、STRICT_ALL_TABLES、NO_ZERO_IN_DATE、NO_ZERO_DATE、ERROR_FOR_DIVISION_BY_ZERO、NO_AUTO_CREATE_USER。




來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22418990/viewspace-753433/,如需轉載,請註明出處,否則將追究法律責任。

相關文章