Mysql集羣-----(附錄1) Mysql5.7 sql_mode 設置

MySQL服務器可以在不同的SQL模式下運行,並且可以根據sql_mode系統變量的值對不同的客戶端應用不同的模式DBA可以設置全局SQL模式以匹配站點服務器操作要求,並且每個應用程序可以將其會話SQL模式設置爲自己的要求。

模式會影響MySQL支持的SQL語法以及它執行的數據驗證檢查。這使得在不同環境中使用MySQL變得更加容易,並且可以將MySQL與其他數據庫服務器一起使用。

有關MySQL中服務器SQL模式常見問題的答案,請參見第A.3節“MySQL 5.7 FAQ:服務器SQL模式”

使用InnoDB表格時,請考慮innodb_strict_mode系統變量。它可以對InnoDB進行額外的錯誤檢查 

設置SQL模式

在MySQL 5.7的默認SQL模式包括以下模式:ONLY_FULL_GROUP_BY, STRICT_TRANS_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATEERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER,和 NO_ENGINE_SUBSTITUTION

這些模式被添加到MySQL 5.7中的默認SQL模式中: ONLY_FULL_GROUP_BY和 STRICT_TRANS_TABLES模式被添加到MySQL 5.7.5中。NO_AUTO_CREATE_USER模式已添加到MySQL 5.7.7中。這些 ERROR_FOR_DIVISION_BY_ZERO, NO_ZERO_DATE和 NO_ZERO_IN_DATE模式都是在MySQL 5.7.8中添加的。有關這些默認SQL模式值更改的更多討論,請參閱 MySQL 5.7中的SQL模式更改

要在服務器啓動時設置SQL模式,請 在命令行或 選項文件(如Unix操作系統)或(Windows)中使用該 選項 。 是用逗號分隔的不同模式的列表。要明確清除SQL模式,請使用命令行或選項文件將其設置爲空字符串 。 --sql-mode="modes"sql-mode="modes"my.cnfmy.inimodes--sql-mode=""sql-mode=""

注意

MySQL安裝程序可能會在安裝過程中配置SQL模式。例如, mysql_install_db將創建一個my.cnf在基本安裝目錄中指定的默認選項文件該文件包含設置SQL模式的行; 請參見第4.4.2節“ mysql_install_db - 初始化MySQL數據目錄”

如果SQL模式與默認或預期不同,請檢查服務器在啓動時讀取的選項文件中的設置。

要在運行時更改SQL模式,請sql_mode使用以下SET 語句設置全局或會話 系統變量

SET GLOBAL sql_mode = 'modes';
SET SESSION sql_mode = 'modes';

設置GLOBAL變量需要 SUPER特權並影響從此時開始連接的所有客戶端的操作。設置SESSION變量僅影響當前客戶端。每個客戶可以隨時更改其會話 sql_mode值。

要確定當前的全局或會話 sql_mode設置,請選擇其值:

SELECT @@GLOBAL.sql_mode;
SELECT @@SESSION.sql_mode;
重要

SQL模式和用戶定義的分區。  創建數據並將其插入分區表後,更改服務器SQL模式可能會導致此類表的行爲發生重大變化,並可能導致數據丟失或損壞。強烈建議您一旦創建了使用用戶定義分區的表格,就不要更改SQL模式。

在複製分區表時,主站和從站上不同的SQL模式也會導致問題。爲了獲得最佳結果,您應始終在主服務器和從服務器上使用相同的服務器SQL模式。

有關更多信息,請參見 第22.6節“分區的限制和限制”

最重要的SQL模式

最重要的sql_mode 價值可能是這些:

  • ANSI

    此模式更改語法和行爲以更貼近地符合標準SQL。它是 本節末尾列出的特殊 組合模式之一。

  • STRICT_TRANS_TABLES

    如果無法將某個值插入到事務表中,請中止該語句。對於非事務性表,如果該值出現在單行語句或多行語句的第一行中,則放棄該語句。更多細節在本節後面給出。

    從MySQL 5.7.5開始,默認的SQL模式包括 STRICT_TRANS_TABLES

  • TRADITIONAL

    讓MySQL像“ 傳統 ” SQL數據庫系統一樣行事在將不正確的值插入列時,此模式的簡單描述是 “ 給出錯誤而不是警告 ”它是本節末尾列出的特殊組合模式之一。

    注意

    隨着TRADITIONAL模式允許,INSERT或者 UPDATE只要發生錯誤中止。如果您使用的是非事務性存儲引擎,則可能不是您想要的,因爲在發生錯誤之前進行的數據更改可能無法回滾,從而導致“ 部分完成 ”更新。

當本手冊引用“ 嚴格模式 ”時,它表示具有一種或兩種STRICT_TRANS_TABLES或 STRICT_ALL_TABLES啓用的模式 

SQL模式的完整列表

以下列表描述了所有支持的SQL模式:

  • ALLOW_INVALID_DATES

    不要執行完整的日期檢查。僅檢查月份是在1到12之間的範圍內,並且日期在1到31之間的範圍內。這對於在三個不同字段中獲取年份,月份和日期的Web應用程序非常有用,並且可以準確存儲用戶插入,沒有日期驗證。此模式適用於 DATE和 DATETIME列。它不適用TIMESTAMP列,它總是需要有效的日期。

    ALLOW_INVALID_DATES 啓用,服務器需要月份和日期值是合法的,而不是僅僅在範圍爲1〜12和1〜31,分別。在禁用嚴格模式的情況下,會生成無效日期(如'2004-04-31'轉換爲 '0000-00-00'和警告)。啓用嚴格模式後,無效日期會生成錯誤。要允許這種日期,請啓用 ALLOW_INVALID_DATES

  • ANSI_QUOTES

    治療"作爲標識符引號字符(如`引號字符),而不是作爲一個字符串引號字符。您仍然可以使用 `引用啓用此模式的標識符。ANSI_QUOTES 啓用,則不能使用雙引號,因爲它們被解釋爲標識符引用文字字符串。

  • ERROR_FOR_DIVISION_BY_ZERO

    該 ERROR_FOR_DIVISION_BY_ZERO 模式影響零除的處理,其中包括 對於數據更改操作(, ),其效果還取決於是否啓用嚴格的SQL模式。 MOD(N,0)INSERTUPDATE

    • 如果此模式未啓用,則按零插入 NULL並不產生警告。

    • 如果啓用此模式,則除以零插入 NULL併產生警告。

    • 如果啓用了此模式和嚴格模式,則除以零除會產生錯誤,除非IGNORE 給出。對於INSERT IGNORE 和UPDATE IGNORE,除以零插入NULL併產生警告。

    因爲SELECT,除以零回報NULLERROR_FOR_DIVISION_BY_ZERO 無論是否啓用嚴格模式,啓用 都會導致產生警告。

    ERROR_FOR_DIVISION_BY_ZERO 已棄用。 ERROR_FOR_DIVISION_BY_ZERO 不是嚴格模式的一部分,但應與嚴格模式配合使用,默認情況下處於啓用狀態。如果ERROR_FOR_DIVISION_BY_ZERO 在未啓用嚴格模式的情況下啓用警告, 反之亦然。有關其他討論,請參閱MySQL 5.7中的SQL模式更改

    由於 ERROR_FOR_DIVISION_BY_ZERO 已被棄用,它將在未來的MySQL版本中作爲單獨的模式名稱被刪除,其影響包含在嚴格SQL模式的影響中。

  • 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 = 'HIGH_NOT_PRECEDENCE';
    mysql> SELECT NOT 1 BETWEEN -5 AND 5;
            -> 1
  • IGNORE_SPACE

    允許函數名稱和(字符之間的空格 這導致內置的函數名稱被視爲保留字。因此,必須按照第9.2節“模式對象名稱”中的描述引用與函數名稱相同的標識符例如,因爲有一個 COUNT()函數,所以count在以下語句中使用 作爲表名稱會導致錯誤:

    mysql> CREATE TABLE count (i INT);
    ERROR 1064 (42000): You have an error in your SQL syntax

    表名應該引用:

    mysql> CREATE TABLE `count` (i INT);
    Query OK, 0 rows affected (0.00 sec)

    IGNORE_SPACESQL模式適用於內置函數,而不是用戶定義的函數或存儲功能。無論是否IGNORE_SPACE啓用,始終允許在UDF或存儲的函數名稱後面有空格 

    有關進一步討論 IGNORE_SPACE,請參見 第9.2.4節“函數名稱解析和解析”

  • NO_AUTO_CREATE_USER

    防止GRANT聲明自動創建新的用戶帳戶,除非認證信息被指定。該聲明必須使用IDENTIFIED BY或使用身份驗證插件指定非空密碼IDENTIFIED WITH

    最好創建MySQL帳戶 CREATE USER而不是 GRANT。 NO_AUTO_CREATE_USER已棄用,默認的SQL模式包含在內NO_AUTO_CREATE_USER分配給sql_mode 該改變 NO_AUTO_CREATE_USER模式狀態產生警告,除了設置分配 sql_mode到 DEFAULTNO_AUTO_CREATE_USER將在未來的MySQL版本中被刪除,此時它的效果將始終啓用(GRANT不會創建帳戶)。

    以前,NO_AUTO_CREATE_USER棄用之前 ,不啓用它的一個原因是它不是複製安全的。現在,它可以啓用和進行復制,安全的用戶管理CREATE USER IF NOT EXISTSDROP USER IF EXISTSALTER USER IF EXISTS而不是 GRANT當從屬服務器與主服務器上的授權可能有不同的授權時,這些語句啓用安全複製。請參見第13.7.1.2節“創建用戶語法”, 第13.7.1.3節“DROP USER語法”和 第13.7.1.1節“ALTER USER語法”

  • NO_AUTO_VALUE_ON_ZERO

    NO_AUTO_VALUE_ON_ZERO 影響AUTO_INCREMENT 列的處理通常情況下,您通過插入NULL或 插入列來生成列的下一個序列號0NO_AUTO_VALUE_ON_ZERO 爲了0NULL產生下一個序列號而抑制這種行爲

    如果0已經存儲在表格的AUTO_INCREMENT 列中,此模式會很有用0順便提一下,存儲不是推薦的做法。)例如,如果您使用mysqldump轉儲表並重新加載它,MySQL通常會在遇到0時生成新的序列號,從而導致與內容不同的表被傾銷。NO_AUTO_VALUE_ON_ZERO 重新加載轉儲文件之前啓用 解決此問題。出於這個原因,mysqldump會在其輸出中自動包含一個使能的語句 NO_AUTO_VALUE_ON_ZERO

  • NO_BACKSLASH_ESCAPES

    禁用反斜槓字符(\)作爲字符串內的轉義字符。啓用此模式後,反斜槓將變成與其他任何其他類似的普通字符。

  • NO_DIR_IN_CREATE

    創建表格時,忽略所有INDEX DIRECTORYDATA DIRECTORY 指令。該選項在從屬複製服務器上很有用。

  • NO_ENGINE_SUBSTITUTION

    控制默認存儲引擎的自動替換,例如CREATE TABLE或者ALTER TABLE指定禁用或未編譯的存儲引擎。

    默認情況下, NO_ENGINE_SUBSTITUTION已啓用。

    由於存儲引擎在運行時可以插入,因此不可用的引擎也會以同樣的方式處理:

    如果 NO_ENGINE_SUBSTITUTION 禁用,CREATE TABLE 則使用默認引擎,如果所需引擎不可用,則會發生警告。因爲 ALTER TABLE,發生警告並且表格未被更改。

    與 NO_ENGINE_SUBSTITUTION 啓用,則會出現錯誤,並且不會創建或修改的表,如果所需的引擎不可用。

  • NO_FIELD_OPTIONS

    不要在輸出中打印MySQL特定的列選項 SHOW CREATE TABLE這種模式在可移植性模式下mysqldump使用

    注意

    從MySQL 5.7.22開始, NO_FIELD_OPTIONS已被棄用。它將在未來版本的MySQL中被刪除。

  • NO_KEY_OPTIONS

    不要在輸出中打印MySQL特定的索引選項 SHOW CREATE TABLE這種模式在可移植性模式下mysqldump使用

    注意

    從MySQL 5.7.22開始, NO_KEY_OPTIONS已被棄用。它將在未來版本的MySQL中被刪除。

  • NO_TABLE_OPTIONS

    不要ENGINE在輸出中打印MySQL特定的表選項(如 ) SHOW CREATE TABLE這種模式在可移植性模式下mysqldump使用

    注意

    從MySQL 5.7.22開始, NO_TABLE_OPTIONS已被棄用。它將在未來版本的MySQL中被刪除。

  • NO_UNSIGNED_SUBTRACTION

    整數值之間的減法(其中一個是類型的 UNSIGNED)會默認生成無符號結果。如果結果是否定的,則會出現錯誤:

    mysql> SET sql_mode = '';
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SELECT CAST(0 AS UNSIGNED) - 1;
    ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(cast(0 as unsigned) - 1)'

    如果NO_UNSIGNED_SUBTRACTION 啓用了 SQL模式,結果是否定的:

    mysql> SET sql_mode = 'NO_UNSIGNED_SUBTRACTION';
    mysql> SELECT CAST(0 AS UNSIGNED) - 1;
    +-------------------------+
    | CAST(0 AS UNSIGNED) - 1 |
    +-------------------------+
    |                      -1 |
    +-------------------------+

    如果此操作的結果用於更新 UNSIGNED整數列,則結果將被剪裁爲列類型的最大值,如果NO_UNSIGNED_SUBTRACTION啓用,則剪切爲0如果啓用嚴格的SQL模式,則會發生錯誤並且列保持不變。

    當 NO_UNSIGNED_SUBTRACTION啓用時,即使任何操作數無符號,減法結果也是有符號的例如,比較列的類型c2在表 t1與該列的 c2t2

    mysql> SET sql_mode='';
    mysql> CREATE TABLE test (c1 BIGINT UNSIGNED NOT NULL);
    mysql> CREATE TABLE t1 SELECT c1 - 1 AS c2 FROM test;
    mysql> DESCRIBE t1;
    +-------+---------------------+------+-----+---------+-------+
    | Field | Type                | Null | Key | Default | Extra |
    +-------+---------------------+------+-----+---------+-------+
    | c2    | bigint(21) unsigned | NO   |     | 0       |       |
    +-------+---------------------+------+-----+---------+-------+
    
    mysql> SET sql_mode='NO_UNSIGNED_SUBTRACTION';
    mysql> CREATE TABLE t2 SELECT c1 - 1 AS c2 FROM test;
    mysql> DESCRIBE t2;
    +-------+------------+------+-----+---------+-------+
    | Field | Type       | Null | Key | Default | Extra |
    +-------+------------+------+-----+---------+-------+
    | c2    | bigint(21) | NO   |     | 0       |       |
    +-------+------------+------+-----+---------+-------+

    這意味着BIGINT UNSIGNED在所有情況下都不是100%可用。請參見 第12.10節“演算函數和操作符”

  • NO_ZERO_DATE

    NO_ZERO_DATE模式影響服務器是否允許 '0000-00-00'作爲有效日期。其效果也取決於是否啓用嚴格的SQL模式。

    • 如果此模式未啓用, '0000-00-00'則允許插入並且不會產生警告。

    • 如果啓用此模式,'0000-00-00' 則允許並插入產生警告。

    • 如果啓用了此模式和嚴格模式, '0000-00-00'則不允許插入並且插入會產生錯誤,除非 IGNORE給出。爲 INSERT IGNOREUPDATE IGNORE'0000-00-00'被允許和插入產生警告。

    NO_ZERO_DATE已棄用。NO_ZERO_DATE 不是嚴格模式的一部分,但應與嚴格模式配合使用,默認情況下處於啓用狀態。如果NO_ZERO_DATE在未啓用嚴格模式的情況下啓用警告, 反之亦然。有關其他討論,請參閱 MySQL 5.7中的SQL模式更改

    由於NO_ZERO_DATE已被棄用,它將在未來的MySQL版本中作爲單獨的模式名稱被刪除,其影響包含在嚴格SQL模式的影響中。

  • NO_ZERO_IN_DATE

    NO_ZERO_IN_DATE模式會影響服務器是否允許年份不爲零,但月份或日期部分爲0的日期。(此模式會影響日期,例如'2010-00-01'或 '2010-01-00',但不是 '0000-00-00'。要控制服務器是否允許'0000-00-00',請使用該 NO_ZERO_DATE模式。)影響的NO_ZERO_IN_DATE 還取決於是否啓用嚴格的SQL模式。

    • 如果未啓用此模式,則允許零部件的日期,並且插入不會產生警告。

    • 如果啓用此模式,則將零件的日期插入'0000-00-00'併產生警告。

    • 如果啓用了此模式和嚴格模式,則不允許帶有零部件的日期,插入會產生錯誤,除非IGNORE給出。對於INSERT IGNORE和 UPDATE IGNORE,具有零部件的日期被插入'0000-00-00'併產生警告。

    NO_ZERO_IN_DATE已棄用。 NO_ZERO_IN_DATE不是嚴格模式的一部分,但應與嚴格模式配合使用,默認情況下處於啓用狀態。如果NO_ZERO_IN_DATE在未啓用嚴格模式的情況下啓用警告, 反之亦然。有關其他討論,請參閱 MySQL 5.7中的SQL模式更改

    由於NO_ZERO_IN_DATE已被棄用,它將在未來的MySQL版本中作爲單獨的模式名稱被刪除,其影響包含在嚴格SQL模式的影響中。

  • ONLY_FULL_GROUP_BY

    拒絕對選擇列表, HAVING條件或ORDER BY列表引用既未在GROUP BY子句中命名也未在功能上依賴(由GROUP BY唯一確定)的非 聚合列的查詢。

    從MySQL 5.7.5開始,默認的SQL模式包括 ONLY_FULL_GROUP_BY(在5.7.5之前,MySQL沒有檢測到函數依賴關係,並且ONLY_FULL_GROUP_BY默認情況下未啓用。關於5.7.5之前的行爲描述,請參閱MySQL 5.6參考手冊。)

    對標準SQL的MySQL擴展允許在HAVING子句中引用 選擇列表中的別名表達式。在MySQL 5.7.5之前,啓用 ONLY_FULL_GROUP_BY 禁用這個擴展,因此需要 HAVING使用非混淆表達式來寫入子句。從MySQL 5.7.5開始,解除了這個限制,這樣HAVING子句可以引用別名,而不管是否 ONLY_FULL_GROUP_BY啓用。

    有關其他討論和示例,請參見 第12.19.3節“MySQL處理GROUP BY”

  • PAD_CHAR_TO_FULL_LENGTH

    默認情況下,尾部空格CHAR在檢索時列值中刪除 如果 PAD_CHAR_TO_FULL_LENGTH啓用,則不會發生修剪,並將檢索 CHAR值填充到全長。此模式不適 VARCHAR用於在檢索時保留尾部空格的列。

    mysql> CREATE TABLE t1 (c1 CHAR(10));
    Query OK, 0 rows affected (0.37 sec)
    
    mysql> INSERT INTO t1 (c1) VALUES('xy');
    Query OK, 1 row affected (0.01 sec)
    
    mysql> SET sql_mode = '';
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SELECT c1, CHAR_LENGTH(c1) FROM t1;
    +------+-----------------+
    | c1   | CHAR_LENGTH(c1) |
    +------+-----------------+
    | xy   |               2 |
    +------+-----------------+
    1 row in set (0.00 sec)
    
    mysql> SET sql_mode = 'PAD_CHAR_TO_FULL_LENGTH';
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SELECT c1, CHAR_LENGTH(c1) FROM t1;
    +------------+-----------------+
    | c1         | CHAR_LENGTH(c1) |
    +------------+-----------------+
    | xy         |              10 |
    +------------+-----------------+
    1 row in set (0.00 sec)
  • PIPES_AS_CONCAT

    治療||作爲字符串並置運算符(同 CONCAT()),而不是作爲一個同義詞OR

  • REAL_AS_FLOAT

    對待REAL作爲一個代名詞 FLOAT默認情況下,MySQL將其REAL視爲一個同義詞 DOUBLE

  • STRICT_ALL_TABLES

    爲所有存儲引擎啓用嚴格的SQL模式。無效的數據值被拒絕。有關詳細信息,請參閱 嚴格SQL模式

    從MySQL 5.7.4通過5.7.7, STRICT_ALL_TABLES包括的效果 ERROR_FOR_DIVISION_BY_ZERO, NO_ZERO_DATE和 NO_ZERO_IN_DATE模式。有關其他討論,請參閱 MySQL 5.7中的SQL模式更改

  • STRICT_TRANS_TABLES

    爲事務性存儲引擎啓用嚴格SQL模式,並在可能的情況下爲非事務性存儲引擎啓用。有關詳細信息,請參閱嚴格SQL模式

    從MySQL 5.7.4通過5.7.7, STRICT_TRANS_TABLES 包括的效果 ERROR_FOR_DIVISION_BY_ZERO, NO_ZERO_DATENO_ZERO_IN_DATE模式。有關其他討論,請參閱 MySQL 5.7中的SQL模式更改

組合SQL模式

提供以下特殊模式作爲上述列表中模式值組合的簡寫。

嚴格的SQL模式

嚴格模式控制MySQL如何處理數據更改語句(如INSERTor)中的 無效值或缺失值 UPDATE由於多種原因,值可能無效。例如,它可能具有該列的錯誤數據類型,或者它可能超出範圍。當要插入的新行不包含定義中NULL沒有顯式DEFAULT子句的非列 的值時,缺少值(對於 NULL列,NULL如果值缺失則插入。)嚴格模式也會影響DDL語句,如CREATE TABLE

如果嚴格模式沒有生效,MySQL會爲無效值或缺失值插入調整值併產生警告(請參見 第13.7.5.40節“SHOW WARNINGS Syntax”)。在嚴格模式下,您可以使用INSERT IGNORE 或生成此行爲 UPDATE IGNORE

對於SELECT 不會更改數據的語句,無效值將在嚴格模式下生成警告,而不是錯誤。

對於嘗試創建超過最大密鑰長度的密鑰的嚴格模式會產生錯誤。如果嚴格模式未啓用,則會導致警告並將密鑰截斷爲最大密鑰長度。

嚴格模式不影響是否檢查外鍵約束。foreign_key_checks可以用於此。(請參見 第5.1.5節“服務器系統變量”。)

如果啓用了STRICT_ALL_TABLES或者 STRICT_TRANS_TABLES已啓用嚴格SQL模式 ,但這些模式的效果有所不同:

  • 對於事務性表,當啓用STRICT_ALL_TABLES或 STRICT_TRANS_TABLES啓用數據更改語句時,無效值或缺失值會發生錯誤 該聲明被中止並回滾。

  • 對於非事務性表,如果在要插入或更新的第一行中出現錯誤值,那麼對於任一模式的行爲都是相同的:語句被中止並且表保持不變。如果語句插入或修改多行,並且第二行或更後一行中出現錯誤值,則結果取決於啓用了哪個嚴格模式:

    • 因爲STRICT_ALL_TABLES,MySQL返回一個錯誤並忽略其餘的行。但是,因爲較早的行已被插入或更新,所以結果是部分更新。爲避免這種情況,請使用單行語句,該語句可以在不更改表格的情況下中止。

    • 因爲 STRICT_TRANS_TABLES,MySQL會將無效值轉換爲列的最接近的有效值並插入調整後的值。如果缺少一個值,MySQL將插入列數據類型的隱式默認值。無論哪種情況,MySQL都會生成警告而不是錯誤,並繼續處理該語句。第11.7節“數據類型默認值”中介紹了隱式默認值

嚴格模式會影響日期中除零,零日期和零的處理,如下所示:

  • 嚴格模式影響零除的處理,其中包括 : MOD(N,0)

    對於數據更改操作(INSERT, UPDATE):

    • 如果嚴格模式未啓用,則除以零插入 NULL並不產生警告。

    • 如果啓用嚴格模式,除非IGNORE零除,否則會產生錯誤對於INSERT IGNORE和 UPDATE IGNORE,除以零插入NULL併產生警告。

    因爲SELECT,除以零回報NULL啓用嚴格模式也會產生警告。

  • 嚴格模式會影響服務器是否允許 '0000-00-00'作爲有效日期:

    • 如果嚴格模式未啓用, '0000-00-00'則允許並且插入不會產生警告。

    • 如果啓用了嚴格模式,'0000-00-00'則不允許插入,並且插入會產生錯誤,除非 IGNORE給出嚴格模式 爲 INSERT IGNOREUPDATE IGNORE'0000-00-00'被允許和插入產生警告。

  • 嚴格模式會影響服務器是否允許年份部分非零但月份或日期部分爲0(日期如'2010-00-01'or '2010-01-00')的日期

    • 如果嚴格模式未啓用,則允許零部件的日期,並且插入不會產生警告。

    • 如果啓用了嚴格模式,則不允許使用零部件的日期,除非IGNORE給出嚴格模式,否則插入會產生錯誤 對於 INSERT IGNOREUPDATE IGNORE,具有零部件的日期被插入 '0000-00-00'(這被認爲是有效的IGNORE)併產生警告。

有關嚴格模式的更多信息 IGNORE,請參閱 IGNORE關鍵字和嚴格SQL模式的比較

MySQL的5.7.4之前,以及在MySQL 5.7.8或更高版本,嚴格模式是零,零日期,並在日期零與一起影響部門的處理ERROR_FOR_DIVISION_BY_ZERO, NO_ZERO_DATE和 NO_ZERO_IN_DATE模式。從MySQL 5.7.4儘管5.7.7的ERROR_FOR_DIVISION_BY_ZERO, NO_ZERO_DATE以及 NO_ZERO_IN_DATE明確命名及其影響都包括在嚴格模式的影響時模式什麼也不做。有關其他討論,請參閱 MySQL 5.7中的SQL模式更改

IGNORE關鍵字和嚴格SQL模式的比較

本節比較IGNORE關鍵字(將錯誤降級爲警告)和嚴格SQL模式(將警告升級爲錯誤)的語句執行效果 它描述了它們影響哪些語句,以及它們適用於哪些錯誤。

下表列出了默認情況下產生錯誤與警告時語句行爲的總結比較。默認情況下產生錯誤的一個示例是將a插入NULLNOT NULL列中。默認情況下產生警告的一個示例是將錯誤數據類型的值插入列(例如將字符串插入 'abc'到整數列中)。

操作模式當語句默認爲錯誤時當語句默認爲警告時
沒有IGNORE或嚴格的SQL模式錯誤警告
同 IGNORE警告警告(與沒有IGNORE或嚴格的SQL模式相同)
採用嚴格的SQL模式錯誤(與沒有IGNORE或嚴格的SQL模式相同)錯誤
採用IGNORE嚴格的SQL模式警告警告

從表中得出的一個結論是,當 IGNORE關鍵字和嚴格SQL模式都有效時,IGNORE優先。這意味着,儘管IGNORE嚴格的SQL模式可以被認爲對錯誤處理有相反的效果,但它們在一起使用時不會取消。

IGNORE對陳述執行的影響

MySQL中的幾個語句支持一個可選的 IGNORE關鍵字。此關鍵字會導致服務器降級某些類型的錯誤並生成警告。對於多行語句, IGNORE會導致語句跳到下一行而不是中止。

例如,如果表t具有主鍵列i,則嘗試將相同的值i插入多行中通常會產生重複鍵錯誤:

mysql> INSERT INTO t (i) VALUES(1),(1);
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'

使用時IGNORE,包含重複鍵的行仍未插入,但會發生警告而不是錯誤:

mysql> INSERT IGNORE INTO t (i) VALUES(1),(1);
Query OK, 1 row affected, 1 warning (0.01 sec)
Records: 2  Duplicates: 1  Warnings: 1

mysql> SHOW WARNINGS;
+---------+------+---------------------------------------+
| Level   | Code | Message                               |
+---------+------+---------------------------------------+
| Warning | 1062 | Duplicate entry '1' for key 'PRIMARY' |
+---------+------+---------------------------------------+
1 row in set (0.00 sec)

這些語句支持IGNORE關鍵字:

  • CREATE TABLE ... SELECTIGNORE不適用於聲明CREATE TABLE或 SELECT部分聲明,而是插入到由聲明產生的行表中 SELECT丟棄在唯一鍵值上覆制現有行的行。

  • DELETE: IGNORE導致MySQL在刪除行的過程中忽略錯誤。

  • INSERT:使用 IGNORE,丟棄在唯一鍵值上覆制現有行的行。將設置爲會導致數據轉換錯誤的值設置爲最接近的有效值。

    對於沒有找到與給定值匹配的分區的分區表,IGNORE會導致插入操作對包含不匹配值的行進行無提示失敗。

  • LOAD DATA, LOAD XML:With IGNORE,丟棄在唯一鍵值上覆制現有行的行。

  • UPDATE:與 IGNORE,在唯一鍵值上發生重複鍵衝突的行不會更新。行更新爲將導致數據轉換錯誤的值更新爲最接近的有效值。

IGNORE關鍵字適用於以下錯誤:

ER_BAD_NULL_ERROR
ER_DUP_ENTRY
ER_DUP_ENTRY_WITH_KEY_NAME
ER_DUP_KEY
ER_NO_PARTITION_FOR_GIVEN_VALUE
ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT
ER_NO_REFERENCED_ROW_2
ER_ROW_DOES_NOT_MATCH_GIVEN_PARTITION_SET
ER_ROW_IS_REFERENCED_2
ER_SUBQUERY_NO_1_ROW
ER_VIEW_CHECK_FAILED
嚴格SQL模式對語句執行的影響

MySQL服務器可以在不同的SQL模式下運行,並且可以根據sql_mode 系統變量的值對不同的客戶端應用不同的模式“ 嚴格 ” SQL模式下,服務器將某些警告升級爲錯誤。

例如,在非嚴格SQL模式下,將字符串插入 'abc'到整數列中會導致將值轉換爲0併發出警告:

mysql> SET sql_mode = '';
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO t (i) VALUES('abc');
Query OK, 1 row affected, 1 warning (0.01 sec)

mysql> SHOW WARNINGS;
+---------+------+--------------------------------------------------------+
| Level   | Code | Message                                                |
+---------+------+--------------------------------------------------------+
| Warning | 1366 | Incorrect integer value: 'abc' for column 'i' at row 1 |
+---------+------+--------------------------------------------------------+
1 row in set (0.00 sec)

在嚴格的SQL模式下,無效值將被拒絕並出現錯誤:

mysql> SET sql_mode = 'STRICT_ALL_TABLES';
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO t (i) VALUES('abc');
ERROR 1366 (HY000): Incorrect integer value: 'abc' for column 'i' at row 1

有關sql_mode系統變量的可能設置的更多信息 ,請參見 第5.1.8節“服務器SQL模式”

嚴格SQL模式適用於下列語句,在某些條件下某些值可能超出範圍,或者將無效行插入或從表中刪除:

在存儲的程序中,如果程序是在嚴格模式生效的情況下定義的,那麼剛剛列出的類型的單個語句將以嚴格的SQL模式執行。

嚴格SQL模式適用於以下錯誤,表示輸入值無效或缺失的一類錯誤。如果該列的數據類型錯誤或者可能超出範圍,則該值無效。如果要插入的新行不包含定義中NOT NULL沒有顯式DEFAULT子句列 的值,則缺少值

ER_BAD_NULL_ERROR
ER_CUT_VALUE_GROUP_CONCAT
ER_DATA_TOO_LONG
ER_DATETIME_FUNCTION_OVERFLOW
ER_DIVISION_BY_ZERO
ER_INVALID_ARGUMENT_FOR_LOGARITHM
ER_NO_DEFAULT_FOR_FIELD
ER_NO_DEFAULT_FOR_VIEW_FIELD
ER_TOO_LONG_KEY
ER_TRUNCATED_WRONG_VALUE
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD
ER_WARN_DATA_OUT_OF_RANGE
ER_WARN_NULL_TO_NOTNULL
ER_WARN_TOO_FEW_RECORDS
ER_WRONG_ARGUMENTS
ER_WRONG_VALUE_FOR_TYPE
WARN_DATA_TRUNCATED

MySQL 5.7中的SQL模式更改

在MySQL 22年7月5日,這些SQL模式被取消,並將在MySQL的未來版本中刪除: DB2, MAXDB, MSSQL, MYSQL323, MYSQL40ORACLE, POSTGRESQL, NO_FIELD_OPTIONS, NO_KEY_OPTIONS, NO_TABLE_OPTIONS

在MySQL 5.7中,ONLY_FULL_GROUP_BY默認情況下啓用了 SQL模式,因爲GROUP BY 處理變得更加複雜,包括檢測功能依賴關係。但是,如果您發現已 ONLY_FULL_GROUP_BY啓用導致現有應用程序的查詢被拒絕,則這些操作中的任何一個都應該恢復操作:

  • 如果可以修改有問題的查詢,請這麼做,以便非聚合列在功能上依賴於GROUP BY列,或者通過使用非聚合列引用 ANY_VALUE()

  • 如果無法修改違規查詢(例如,如果它是由第三方應用程序生成的),請sql_mode在服務器啓動時系統變量設置爲不啓用ONLY_FULL_GROUP_BY

在MySQL 5.7中, ERROR_FOR_DIVISION_BY_ZERO, NO_ZERO_DATE,和 NO_ZERO_IN_DATESQL模式已被棄用。長期計劃是將三種模式納入嚴格的SQL模式,並將其作爲未來MySQL版本中的顯式模式進行移除。爲了兼容MySQL 5.7和MySQL 5.6嚴格模式併爲受影響的應用程序提供更多時間修改,以下行爲適用:

通過上述更改,默認情況下仍會啓用更嚴格的數據檢查,但可以在當前希望或必須執行此操作的環境中禁用各個模式

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章