文件首頁
MySQL 9.0 參考手冊
相關文件 下載本手冊
PDF (美國信紙) - 40.0Mb
PDF (A4) - 40.1Mb
Man Pages (TGZ) - 258.2Kb
Man Pages (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 9.0 參考手冊  /  ...  /  伺服器 SQL 模式

7.1.11 伺服器 SQL 模式

MySQL 伺服器可以在不同的 SQL 模式下運作,並且可以根據 sql_mode 系統變數的值,針對不同的用戶端套用這些模式。DBA 可以設定全域 SQL 模式以符合網站伺服器的運作需求,而每個應用程式都可以將其工作階段 SQL 模式設定為自己的需求。

模式會影響 MySQL 支援的 SQL 語法及其執行的資料驗證檢查。這使得在不同環境中使用 MySQL 以及將 MySQL 與其他資料庫伺服器一起使用變得更加容易。

如需關於 MySQL 中伺服器 SQL 模式的常見問題解答,請參閱 第 A.3 節,「MySQL 9.0 常見問題:伺服器 SQL 模式」

使用 InnoDB 資料表時,也請考慮 innodb_strict_mode 系統變數。它會為 InnoDB 資料表啟用其他錯誤檢查。

設定 SQL 模式

MySQL 9.0 中的預設 SQL 模式包含以下模式:ONLY_FULL_GROUP_BYSTRICT_TRANS_TABLESNO_ZERO_IN_DATENO_ZERO_DATEERROR_FOR_DIVISION_BY_ZERONO_ENGINE_SUBSTITUTION

若要在伺服器啟動時設定 SQL 模式,請在命令列上使用 --sql-mode="modes" 選項,或在選項檔案 (例如 my.cnf (Unix 作業系統) 或 my.ini (Windows)) 中使用 sql-mode="modes"modes 是以逗號分隔的不同模式清單。若要明確清除 SQL 模式,請在命令列上使用 --sql-mode="",或在選項檔案中使用 sql-mode="",將其設定為空字串。

注意

MySQL 安裝程式可能會在安裝過程中設定 SQL 模式。

如果 SQL 模式與預設值或您預期的值不同,請檢查伺服器在啟動時讀取的選項檔案中是否有設定。

若要在執行階段變更 SQL 模式,請使用 SET 陳述式設定全域或工作階段 sql_mode 系統變數

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

設定 GLOBAL 變數需要 SYSTEM_VARIABLES_ADMIN 權限 (或已過時的 SUPER 權限),並會影響從那時起連線的所有用戶端的運作。設定 SESSION 變數只會影響目前的用戶端。每個用戶端都可以隨時變更其工作階段 sql_mode 值。

若要判斷目前的全域或工作階段 sql_mode 設定,請選取其值

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

SQL 模式和使用者定義分割區。在建立分割區資料表並將資料插入其中之後變更伺服器 SQL 模式,可能會導致此類資料表的行為發生重大變更,並可能導致資料遺失或損毀。強烈建議您在建立使用使用者定義分割區的資料表之後,絕不要變更 SQL 模式。

複寫分割區資料表時,來源和複本上不同的 SQL 模式也可能導致問題。為了獲得最佳結果,您應該始終在來源和複本上使用相同的伺服器 SQL 模式。

如需更多資訊,請參閱 第 26.6 節,「分割區的限制和限制」

最重要的 SQL 模式

最重要的 sql_mode 值可能是這些

  • ANSI

    此模式會變更語法和行為,使其更符合標準 SQL。它是本節末尾列出的特殊組合模式之一。

  • STRICT_TRANS_TABLES

    如果無法將值如實插入事務表中,則中止語句。對於非事務表,如果該值出現在單列語句或多列語句的第一列中,則中止語句。本節稍後會提供更多詳細資訊。

  • TRADITIONAL

    讓 MySQL 的行為類似於「傳統」SQL 資料庫系統。此模式的簡單描述是,當將不正確的值插入資料行時,會「給出錯誤而不是警告」。它是本節末尾列出的特殊組合模式之一。

    注意

    啟用 TRADITIONAL 模式後,INSERTUPDATE 會在發生錯誤時立即中止。如果您使用的是非事務儲存引擎,這可能不是您想要的,因為在錯誤發生之前所做的資料變更可能不會回滾,導致「部分完成」的更新。

當本手冊提到「嚴格模式」時,它指的是啟用 STRICT_TRANS_TABLESSTRICT_ALL_TABLES 其中之一或兩者的模式。

SQL 模式的完整清單

以下清單描述了所有支援的 SQL 模式

  • ALLOW_INVALID_DATES

    不執行完整的日期檢查。僅檢查月份是否在 1 到 12 的範圍內,以及日期是否在 1 到 31 的範圍內。這對於網頁應用程式可能很有用,這些應用程式在三個不同的欄位中取得年、月和日,並儲存使用者插入的確切內容,而無需進行日期驗證。此模式適用於 DATEDATETIME 資料行。它不適用於 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 模式會影響處理除以零的情況,包括 MOD(N,0)。對於資料變更作業(INSERTUPDATE),其影響還取決於是否啟用嚴格 SQL 模式。

    • 如果未啟用此模式,則除以零會插入 NULL,且不會產生任何警告。

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

    • 如果同時啟用此模式和嚴格模式,則除以零會產生錯誤,除非同時給出 IGNORE。對於 INSERT IGNOREUPDATE IGNORE,除以零會插入 NULL,並產生警告。

    對於 SELECT,除以零會傳回 NULL。啟用 ERROR_FOR_DIVISION_BY_ZERO 也會產生警告,無論是否啟用嚴格模式。

    ERROR_FOR_DIVISION_BY_ZERO 已被棄用。ERROR_FOR_DIVISION_BY_ZERO 不是嚴格模式的一部分,但應與嚴格模式結合使用,且預設為啟用。如果啟用 ERROR_FOR_DIVISION_BY_ZERO 而不啟用嚴格模式,反之亦然,則會發生警告。

    由於 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_PRECEDENCE SQL 模式來取得舊的較高優先順序行為。

    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

    允許函數名稱和 ( 字元之間有空格。這會導致內建函數名稱被視為保留字。因此,與函數名稱相同的識別碼必須如第 11.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_SPACE SQL 模式適用於內建函數,而不適用於可載入函數或預存函數。始終允許在可載入函數或預存函數名稱之後有空格,無論是否啟用 IGNORE_SPACE

    如需有關 IGNORE_SPACE 的進一步討論,請參閱第 11.2.5 節「函數名稱剖析和解析」

  • NO_AUTO_VALUE_ON_ZERO

    NO_AUTO_VALUE_ON_ZERO 會影響 AUTO_INCREMENT 資料行的處理。通常,您可以透過將 NULL0 插入資料行中,來產生該資料行的下一個序號。NO_AUTO_VALUE_ON_ZERO 會抑制 0 的這種行為,因此只有 NULL 會產生下一個序號。

    如果 0 已儲存在表格的 AUTO_INCREMENT 資料行中,則此模式會很有用。(順帶一提,不建議儲存 0。)例如,如果您使用 mysqldump 傾印表格,然後重新載入該表格,則 MySQL 通常會在遇到 0 值時產生新的序號,導致表格的內容與傾印的內容不同。在重新載入傾印檔案之前啟用 NO_AUTO_VALUE_ON_ZERO,即可解決此問題。因此,mysqldump 會在其輸出中自動包含一個語句,該語句會啟用 NO_AUTO_VALUE_ON_ZERO

  • NO_BACKSLASH_ESCAPES

    啟用此模式會停用使用反斜線字元 (\) 作為字串和識別碼內的跳脫字元。啟用此模式後,反斜線會變成與其他任何字元相同的普通字元,而 LIKE 運算式的預設跳脫序列會變更為不使用跳脫字元。

  • NO_DIR_IN_CREATE

    在建立表格時,忽略所有 INDEX DIRECTORYDATA DIRECTORY 指令。此選項在複本伺服器上很有用。

  • NO_ENGINE_SUBSTITUTION

    控制在 CREATE TABLEALTER TABLE 等語句指定已停用或未編譯的儲存引擎時,自動取代預設儲存引擎。

    預設情況下,NO_ENGINE_SUBSTITUTION 為啟用。

    由於儲存引擎可以在執行時外掛,因此無法使用的引擎會被以相同的方式對待。

    在停用 NO_ENGINE_SUBSTITUTION 的情況下,對於 CREATE TABLE,如果所需的引擎無法使用,則會使用預設引擎並產生警告。對於 ALTER TABLE,會產生警告且不會變更表格。

    在啟用 NO_ENGINE_SUBSTITUTION 的情況下,如果所需的引擎無法使用,則會發生錯誤,且不會建立或變更表格。

  • 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 時,減法結果為有符號,即使任何運算元為無符號。例如,比較表格 t1 中欄位 c2 的類型與表格 t2 中欄位 c2 的類型。

    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% 可用。請參閱第 14.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 但未同時啟用嚴格模式,或反之,則會發生警告。

    由於 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 IGNOREUPDATE IGNORE,具有零部分的日期會以 '0000-00-00' 插入,並產生警告。

    NO_ZERO_IN_DATE 已過時。NO_ZERO_IN_DATE 不是嚴格模式的一部分,但應與嚴格模式一起使用,且預設為啟用。如果啟用 NO_ZERO_IN_DATE 但未同時啟用嚴格模式,或反之,則會發生警告。

    由於 NO_ZERO_IN_DATE 已過時,您應預期它會在未來的 MySQL 版本中作為單獨的模式名稱被移除,並且其效果將包含在嚴格 SQL 模式的效果中。

  • ONLY_FULL_GROUP_BY

    拒絕選取清單、HAVING 條件或 ORDER BY 清單引用未在 GROUP BY 子句中命名,也未在功能上依賴於(由 GROUP BY 欄位唯一確定)GROUP BY 欄位的非聚合欄位的查詢。

    標準 SQL 的 MySQL 擴充功能允許在 HAVING 子句中引用選取清單中的別名運算式。HAVING 子句可以引用別名,無論是否啟用 ONLY_FULL_GROUP_BY

    有關其他討論和範例,請參閱第 14.19.3 節,「MySQL 的 GROUP BY 處理」

  • PAD_CHAR_TO_FULL_LENGTH

    預設情況下,在擷取時會從 CHAR 欄位值中修剪尾隨空格。如果啟用 PAD_CHAR_TO_FULL_LENGTH,則不會進行修剪,並且擷取的 CHAR 值會填補到其完整長度。此模式不適用於 VARCHAR 欄位,在擷取時會保留其尾隨空格。

    注意

    PAD_CHAR_TO_FULL_LENGTH 已過時。預期它會在未來的 MySQL 版本中被移除。

    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 模式

  • STRICT_TRANS_TABLES

    為交易型儲存引擎啟用嚴格 SQL 模式,並在可能的情況下為非交易型儲存引擎啟用。有關詳細資訊,請參閱嚴格 SQL 模式

  • TIME_TRUNCATE_FRACTIONAL

    控制當插入一個具有小數秒部分的 TIMEDATETIMESTAMP 值到具有相同類型但小數點位數較少的欄位時,是否發生捨入或截斷。預設行為是使用捨入。如果啟用此模式,則改為發生截斷。以下語句序列說明了差異:

    CREATE TABLE t (id INT, tval TIME(1));
    SET sql_mode='';
    INSERT INTO t (id, tval) VALUES(1, 1.55);
    SET sql_mode='TIME_TRUNCATE_FRACTIONAL';
    INSERT INTO t (id, tval) VALUES(2, 1.55);

    產生的表格內容如下所示,其中第一個值已進行捨入,第二個值已進行截斷:

    mysql> SELECT id, tval FROM t ORDER BY id;
    +------+------------+
    | id   | tval       |
    +------+------------+
    |    1 | 00:00:01.6 |
    |    2 | 00:00:01.5 |
    +------+------------+

    另請參閱第 13.2.6 節,「時間值中的小數秒」

組合 SQL 模式

以下特殊模式提供作為先前列表中模式值的組合的簡寫。

嚴格 SQL 模式

嚴格模式控制 MySQL 如何處理資料變更陳述式(例如 INSERTUPDATE)中的無效或遺失值。數值無效的原因有很多。例如,數值的資料類型可能與資料行不符,或可能超出範圍。當要插入的新列沒有包含非 NULL 資料行(且該資料行在其定義中沒有明確的 DEFAULT 子句)的值時,數值會遺失。(對於 NULL 資料行,如果數值遺失,則會插入 NULL。)嚴格模式也會影響 DDL 陳述式,例如 CREATE TABLE

如果未啟用嚴格模式,MySQL 會插入已調整的無效或遺失值,並產生警告(請參閱 章節 15.7.7.41,「SHOW WARNINGS 陳述式」)。在嚴格模式下,您可以使用 INSERT IGNOREUPDATE IGNORE 來產生此行為。

對於不會變更資料的陳述式(例如 SELECT),無效值在嚴格模式下會產生警告,而不是錯誤。

如果嘗試建立超過最大索引鍵長度的索引鍵,嚴格模式會產生錯誤。如果未啟用嚴格模式,則會產生警告,並將索引鍵截斷為最大索引鍵長度。

嚴格模式不會影響是否檢查外來索引鍵限制。 可以使用 foreign_key_checks 來進行檢查。(請參閱 章節 7.1.8,「伺服器系統變數」。)

如果啟用 STRICT_ALL_TABLESSTRICT_TRANS_TABLES 其中之一,則會啟用嚴格 SQL 模式,儘管這些模式的效果略有不同。

  • 對於交易型資料表,當啟用 STRICT_ALL_TABLESSTRICT_TRANS_TABLES 其中之一時,在資料變更陳述式中發現無效或遺失值會發生錯誤。陳述式會中止並復原。

  • 對於非交易型資料表,如果錯誤值出現在要插入或更新的第一列,則無論啟用哪種模式,行為都相同:陳述式會中止,且資料表保持不變。如果陳述式插入或修改多列,且錯誤值出現在第二列或後續列,則結果取決於啟用哪種嚴格模式。

    • 對於 STRICT_ALL_TABLES,MySQL 會傳回錯誤並忽略其餘列。但是,由於先前的列已插入或更新,因此結果為部分更新。若要避免此情況,請使用單列陳述式,這樣可以中止而不變更資料表。

    • 對於 STRICT_TRANS_TABLES,MySQL 會將無效值轉換為最接近資料行有效的值,並插入已調整的值。如果值遺失,MySQL 會插入資料行資料類型的隱含預設值。無論哪種情況,MySQL 都會產生警告,而不是錯誤,並繼續處理陳述式。隱含預設值在 章節 13.6,「資料類型預設值」中說明。

嚴格模式會以下列方式影響除以零、零日期和日期中的零的處理方式。

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

    對於資料變更作業(INSERTUPDATE):

    • 如果未啟用嚴格模式,除以零會插入 NULL,且不會產生警告。

    • 如果啟用嚴格模式,除以零會產生錯誤,除非也指定 IGNORE。對於 INSERT IGNOREUPDATE IGNORE,除以零會插入 NULL 並產生警告。

    對於 SELECT,除以零會傳回 NULL。啟用嚴格模式也會產生警告。

  • 嚴格模式會影響伺服器是否允許 '0000-00-00' 作為有效日期。

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

    • 如果啟用嚴格模式,則不允許 '0000-00-00',且插入會產生錯誤,除非也指定 IGNORE。對於 INSERT IGNOREUPDATE IGNORE,允許 '0000-00-00',且插入會產生警告。

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

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

    • 如果啟用嚴格模式,則不允許使用零部分的日期,且插入會產生錯誤,除非也指定 IGNORE。對於 INSERT IGNOREUPDATE IGNORE,帶有零部分的日期會插入為 '0000-00-00'(在使用 IGNORE 時,會將其視為有效),並產生警告。

如需有關搭配 IGNORE 使用嚴格模式的詳細資訊,請參閱「IGNORE 關鍵字與嚴格 SQL 模式的比較」

嚴格模式會影響搭配 ERROR_FOR_DIVISION_BY_ZERONO_ZERO_DATENO_ZERO_IN_DATE 模式,處理除以零、零日期和日期中的零。

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

本節比較 IGNORE 關鍵字(將錯誤降級為警告)和嚴格 SQL 模式(將警告升級為錯誤)對陳述式執行的影響。它說明它們影響哪些陳述式,以及它們套用到哪些錯誤。

下表總結了陳述式在預設產生錯誤與警告時的行為比較。預設產生錯誤的一個範例是將 NULL 插入 NOT NULL 資料行。預設產生警告的一個範例是將錯誤的資料類型的值插入資料行(例如將字串 'abc' 插入整數資料行)。

運作模式 當陳述式預設為錯誤時 當陳述式預設為警告時
沒有 IGNORE 或嚴格 SQL 模式 錯誤 警告
IGNORE 警告 警告(與沒有 IGNORE 或嚴格 SQL 模式時相同)
有嚴格 SQL 模式 錯誤(與沒有 IGNORE 或嚴格 SQL 模式時相同) 錯誤
IGNORE 和嚴格 SQL 模式 警告 警告

從表中得出的一個結論是,當 IGNORE 關鍵字和嚴格 SQL 模式同時生效時,IGNORE 優先。這表示,雖然可以認為 IGNORE 和嚴格 SQL 模式對錯誤處理有相反的影響,但它們一起使用時不會互相抵消。

IGNORE 對陳述式執行的影響

MySQL 中的數個陳述式支援選用的 IGNORE 關鍵字。此關鍵字會導致伺服器將某些類型的錯誤降級,並改為產生警告。對於多列陳述式,將錯誤降級為警告可能會啟用處理列。否則,IGNORE 會導致陳述式跳到下一列,而不是中止。(對於不可忽略的錯誤,無論 IGNORE 關鍵字如何,都會發生錯誤。)

範例:如果資料表 t 有一個包含唯一值的索引鍵資料行 i,嘗試將相同的 i 值插入多列通常會產生重複索引鍵錯誤。

mysql> CREATE TABLE t (i INT NOT NULL PRIMARY KEY);
mysql> INSERT INTO t (i) VALUES(1),(1);
ERROR 1062 (23000): Duplicate entry '1' for key 't.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 't.PRIMARY' |
+---------+------+-----------------------------------------+
1 row in set (0.00 sec)

範例:如果資料表 t2 有一個 NOT NULL 資料行 id,嘗試插入 NULL 會在嚴格 SQL 模式下產生錯誤。

mysql> CREATE TABLE t2 (id INT NOT NULL);
mysql> INSERT INTO t2 (id) VALUES(1),(NULL),(3);
ERROR 1048 (23000): Column 'id' cannot be null
mysql> SELECT * FROM t2;
Empty set (0.00 sec)

如果 SQL 模式不是嚴格模式,IGNORE 會導致 NULL 作為資料行的隱含預設值(在本例中為 0)插入,這會啟用處理列而不跳過它。

mysql> INSERT INTO t2 (id) VALUES(1),(NULL),(3);
mysql> SELECT * FROM t2;
+----+
| id |
+----+
|  1 |
|  0 |
|  3 |
+----+

這些陳述式支援 IGNORE 關鍵字:

  • CREATE TABLE ... SELECTIGNORE 不適用於陳述式的 CREATE TABLESELECT 部分,而是適用於插入 SELECT 所產生列的資料表。會捨棄在唯一索引鍵值上與現有列重複的列。

  • DELETEIGNORE 會導致 MySQL 在刪除列的過程中忽略錯誤。

  • INSERT:使用 IGNORE 時,會捨棄在唯一索引鍵值上與現有列重複的列。設定為會導致資料轉換錯誤的值的列,會改為設定為最接近的有效值。

    對於分割表格,如果找不到符合給定值的分割區,IGNORE 會導致包含不符合值之列的插入操作靜默失敗。

  • LOAD DATALOAD XML:使用 IGNORE 時,在唯一鍵值上重複現有列的列會被捨棄。

  • UPDATE:使用 IGNORE 時,在唯一鍵值上發生重複鍵衝突的列不會被更新。更新為會導致資料轉換錯誤的值的列,會改為更新為最接近的有效值。

IGNORE 關鍵字適用於以下可忽略的錯誤

嚴格 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 系統變數的可能設定的更多資訊,請參閱第 7.1.11 節,「伺服器 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 開發定義了新的錯誤,因此可能會有未包含在上述清單中,但適用於嚴格 SQL 模式的錯誤。