MySQL 伺服器可以在不同的 SQL 模式下運作,並且可以根據 sql_mode
系統變數的值,針對不同的用戶端套用這些模式。DBA 可以設定全域 SQL 模式以符合網站伺服器的運作需求,而每個應用程式都可以將其工作階段 SQL 模式設定為自己的需求。
模式會影響 MySQL 支援的 SQL 語法及其執行的資料驗證檢查。這使得在不同環境中使用 MySQL 以及將 MySQL 與其他資料庫伺服器一起使用變得更加容易。
如需關於 MySQL 中伺服器 SQL 模式的常見問題解答,請參閱 第 A.3 節,「MySQL 9.0 常見問題:伺服器 SQL 模式」。
使用 InnoDB
資料表時,也請考慮 innodb_strict_mode
系統變數。它會為 InnoDB
資料表啟用其他錯誤檢查。
MySQL 9.0 中的預設 SQL 模式包含以下模式:ONLY_FULL_GROUP_BY
、STRICT_TRANS_TABLES
、NO_ZERO_IN_DATE
、NO_ZERO_DATE
、ERROR_FOR_DIVISION_BY_ZERO
和 NO_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_mode
值可能是這些
此模式會變更語法和行為,使其更符合標準 SQL。它是本節末尾列出的特殊組合模式之一。
如果無法將值如實插入事務表中,則中止語句。對於非事務表,如果該值出現在單列語句或多列語句的第一列中,則中止語句。本節稍後會提供更多詳細資訊。
讓 MySQL 的行為類似於「“傳統”」SQL 資料庫系統。此模式的簡單描述是,當將不正確的值插入資料行時,會「“給出錯誤而不是警告”」。它是本節末尾列出的特殊組合模式之一。
注意啟用
TRADITIONAL
模式後,INSERT
或UPDATE
會在發生錯誤時立即中止。如果您使用的是非事務儲存引擎,這可能不是您想要的,因為在錯誤發生之前所做的資料變更可能不會回滾,導致「“部分完成”」的更新。
當本手冊提到「“嚴格模式”」時,它指的是啟用 STRICT_TRANS_TABLES
或 STRICT_ALL_TABLES
其中之一或兩者的模式。
以下清單描述了所有支援的 SQL 模式
不執行完整的日期檢查。僅檢查月份是否在 1 到 12 的範圍內,以及日期是否在 1 到 31 的範圍內。這對於網頁應用程式可能很有用,這些應用程式在三個不同的欄位中取得年、月和日,並儲存使用者插入的確切內容,而無需進行日期驗證。此模式適用於
DATE
和DATETIME
資料行。它不適用於TIMESTAMP
資料行,該資料行始終需要有效的日期。停用
ALLOW_INVALID_DATES
時,伺服器要求月份和日期值必須合法,而不僅僅是在 1 到 12 和 1 到 31 的範圍內。如果停用嚴格模式,則無效的日期(例如'2004-04-31'
)會轉換為'0000-00-00'
,並產生警告。如果啟用嚴格模式,則無效的日期會產生錯誤。若要允許此類日期,請啟用ALLOW_INVALID_DATES
。將
"
視為識別碼引號字元(如`
引號字元),而不是字串引號字元。您仍然可以使用`
來引號已啟用此模式的識別碼。啟用ANSI_QUOTES
時,您無法使用雙引號來引號常值字串,因為它們會被解譯為識別碼。ERROR_FOR_DIVISION_BY_ZERO
模式會影響處理除以零的情況,包括MOD(
。對於資料變更作業(N
,0)INSERT
、UPDATE
),其影響還取決於是否啟用嚴格 SQL 模式。如果未啟用此模式,則除以零會插入
NULL
,且不會產生任何警告。如果啟用此模式,則除以零會插入
NULL
,並產生警告。如果同時啟用此模式和嚴格模式,則除以零會產生錯誤,除非同時給出
IGNORE
。對於INSERT IGNORE
和UPDATE 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 模式的效果中。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
允許函數名稱和
(
字元之間有空格。這會導致內建函數名稱被視為保留字。因此,與函數名稱相同的識別碼必須如第 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
會影響AUTO_INCREMENT
資料行的處理。通常,您可以透過將NULL
或0
插入資料行中,來產生該資料行的下一個序號。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
。啟用此模式會停用使用反斜線字元 (
\
) 作為字串和識別碼內的跳脫字元。啟用此模式後,反斜線會變成與其他任何字元相同的普通字元,而LIKE
運算式的預設跳脫序列會變更為不使用跳脫字元。在建立表格時,忽略所有
INDEX DIRECTORY
和DATA DIRECTORY
指令。此選項在複本伺服器上很有用。控制在
CREATE TABLE
或ALTER TABLE
等語句指定已停用或未編譯的儲存引擎時,自動取代預設儲存引擎。預設情況下,
NO_ENGINE_SUBSTITUTION
為啟用。由於儲存引擎可以在執行時外掛,因此無法使用的引擎會被以相同的方式對待。
在停用
NO_ENGINE_SUBSTITUTION
的情況下,對於CREATE TABLE
,如果所需的引擎無法使用,則會使用預設引擎並產生警告。對於ALTER TABLE
,會產生警告且不會變更表格。在啟用
NO_ENGINE_SUBSTITUTION
的情況下,如果所需的引擎無法使用,則會發生錯誤,且不會建立或變更表格。預設情況下,整數值之間的減法,其中一個為
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
模式會影響伺服器是否允許'0000-00-00'
作為有效日期。其效果也取決於是否啟用嚴格 SQL 模式。如果未啟用此模式,則允許使用
'0000-00-00'
,且插入不會產生警告。如果啟用此模式,則允許使用
'0000-00-00'
,且插入會產生警告。如果同時啟用此模式和嚴格模式,則不允許使用
'0000-00-00'
,且插入會產生錯誤,除非同時給定IGNORE
。對於INSERT IGNORE
和UPDATE IGNORE
,允許使用'0000-00-00'
,且插入會產生警告。
NO_ZERO_DATE
已過時。NO_ZERO_DATE
不是嚴格模式的一部分,但應與嚴格模式一起使用,且預設為啟用。如果啟用NO_ZERO_DATE
但未同時啟用嚴格模式,或反之,則會發生警告。由於
NO_ZERO_DATE
已過時,您應預期它會在未來的 MySQL 版本中作為單獨的模式名稱被移除,並且其效果將包含在嚴格 SQL 模式的效果中。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
但未同時啟用嚴格模式,或反之,則會發生警告。由於
NO_ZERO_IN_DATE
已過時,您應預期它會在未來的 MySQL 版本中作為單獨的模式名稱被移除,並且其效果將包含在嚴格 SQL 模式的效果中。拒絕選取清單、
HAVING
條件或ORDER BY
清單引用未在GROUP BY
子句中命名,也未在功能上依賴於(由GROUP BY
欄位唯一確定)GROUP BY
欄位的非聚合欄位的查詢。標準 SQL 的 MySQL 擴充功能允許在
HAVING
子句中引用選取清單中的別名運算式。HAVING
子句可以引用別名,無論是否啟用ONLY_FULL_GROUP_BY
。有關其他討論和範例,請參閱第 14.19.3 節,「MySQL 的 GROUP BY 處理」。
預設情況下,在擷取時會從
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)
為所有儲存引擎啟用嚴格 SQL 模式。無效的資料值會被拒絕。有關詳細資訊,請參閱嚴格 SQL 模式。
為交易型儲存引擎啟用嚴格 SQL 模式,並在可能的情況下為非交易型儲存引擎啟用。有關詳細資訊,請參閱嚴格 SQL 模式。
控制當插入一個具有小數秒部分的
TIME
、DATE
或TIMESTAMP
值到具有相同類型但小數點位數較少的欄位時,是否發生捨入或截斷。預設行為是使用捨入。如果啟用此模式,則改為發生截斷。以下語句序列說明了差異: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 | +------+------------+
以下特殊模式提供作為先前列表中模式值的組合的簡寫。
等同於
REAL_AS_FLOAT
、PIPES_AS_CONCAT
、ANSI_QUOTES
、IGNORE_SPACE
和ONLY_FULL_GROUP_BY
。ANSI
模式也會導致伺服器針對集合函式S
具有外部參考
無法在已解析外部參考的外部查詢中聚合的查詢傳回錯誤。這就是這樣一個查詢:S
(outer_ref
)SELECT * FROM t1 WHERE t1.a IN (SELECT MAX(t1.b) FROM t2 WHERE ...);
在這裡,
MAX(t1.b)
無法在外部查詢中聚合,因為它出現在該查詢的WHERE
子句中。標準 SQL 在這種情況下需要錯誤。如果未啟用ANSI
模式,則伺服器會以相同的方式處理此類查詢中的
,就像它會解釋S
(outer_ref
)
一樣。S
(const
)TRADITIONAL
等同於STRICT_TRANS_TABLES
、STRICT_ALL_TABLES
、NO_ZERO_IN_DATE
、NO_ZERO_DATE
、ERROR_FOR_DIVISION_BY_ZERO
和NO_ENGINE_SUBSTITUTION
。
嚴格模式控制 MySQL 如何處理資料變更陳述式(例如 INSERT
或 UPDATE
)中的無效或遺失值。數值無效的原因有很多。例如,數值的資料類型可能與資料行不符,或可能超出範圍。當要插入的新列沒有包含非 NULL
資料行(且該資料行在其定義中沒有明確的 DEFAULT
子句)的值時,數值會遺失。(對於 NULL
資料行,如果數值遺失,則會插入 NULL
。)嚴格模式也會影響 DDL 陳述式,例如 CREATE TABLE
。
如果未啟用嚴格模式,MySQL 會插入已調整的無效或遺失值,並產生警告(請參閱 章節 15.7.7.41,「SHOW WARNINGS 陳述式」)。在嚴格模式下,您可以使用 INSERT IGNORE
或 UPDATE IGNORE
來產生此行為。
對於不會變更資料的陳述式(例如 SELECT
),無效值在嚴格模式下會產生警告,而不是錯誤。
如果嘗試建立超過最大索引鍵長度的索引鍵,嚴格模式會產生錯誤。如果未啟用嚴格模式,則會產生警告,並將索引鍵截斷為最大索引鍵長度。
嚴格模式不會影響是否檢查外來索引鍵限制。 可以使用 foreign_key_checks
來進行檢查。(請參閱 章節 7.1.8,「伺服器系統變數」。)
如果啟用 STRICT_ALL_TABLES
或 STRICT_TRANS_TABLES
其中之一,則會啟用嚴格 SQL 模式,儘管這些模式的效果略有不同。
對於交易型資料表,當啟用
STRICT_ALL_TABLES
或STRICT_TRANS_TABLES
其中之一時,在資料變更陳述式中發現無效或遺失值會發生錯誤。陳述式會中止並復原。對於非交易型資料表,如果錯誤值出現在要插入或更新的第一列,則無論啟用哪種模式,行為都相同:陳述式會中止,且資料表保持不變。如果陳述式插入或修改多列,且錯誤值出現在第二列或後續列,則結果取決於啟用哪種嚴格模式。
對於
STRICT_ALL_TABLES
,MySQL 會傳回錯誤並忽略其餘列。但是,由於先前的列已插入或更新,因此結果為部分更新。若要避免此情況,請使用單列陳述式,這樣可以中止而不變更資料表。對於
STRICT_TRANS_TABLES
,MySQL 會將無效值轉換為最接近資料行有效的值,並插入已調整的值。如果值遺失,MySQL 會插入資料行資料類型的隱含預設值。無論哪種情況,MySQL 都會產生警告,而不是錯誤,並繼續處理陳述式。隱含預設值在 章節 13.6,「資料類型預設值」中說明。
嚴格模式會以下列方式影響除以零、零日期和日期中的零的處理方式。
嚴格模式會影響除以零的處理方式,其中包括
MOD(
。N
,0)如果未啟用嚴格模式,除以零會插入
NULL
,且不會產生警告。如果啟用嚴格模式,除以零會產生錯誤,除非也指定
IGNORE
。對於INSERT IGNORE
和UPDATE IGNORE
,除以零會插入NULL
並產生警告。
對於
SELECT
,除以零會傳回NULL
。啟用嚴格模式也會產生警告。嚴格模式會影響伺服器是否允許
'0000-00-00'
作為有效日期。如果未啟用嚴格模式,則允許
'0000-00-00'
,且插入不會產生警告。如果啟用嚴格模式,則不允許
'0000-00-00'
,且插入會產生錯誤,除非也指定IGNORE
。對於INSERT IGNORE
和UPDATE IGNORE
,允許'0000-00-00'
,且插入會產生警告。
嚴格模式會影響伺服器是否允許年份部分非零,但月份或日期部分為 0 的日期(例如
'2010-00-01'
或'2010-01-00'
)。如果未啟用嚴格模式,則允許使用零部分的日期,且插入不會產生警告。
如果啟用嚴格模式,則不允許使用零部分的日期,且插入會產生錯誤,除非也指定
IGNORE
。對於INSERT IGNORE
和UPDATE IGNORE
,帶有零部分的日期會插入為'0000-00-00'
(在使用IGNORE
時,會將其視為有效),並產生警告。
如需有關搭配 IGNORE
使用嚴格模式的詳細資訊,請參閱「IGNORE 關鍵字與嚴格 SQL 模式的比較」。
嚴格模式會影響搭配 ERROR_FOR_DIVISION_BY_ZERO
、NO_ZERO_DATE
和 NO_ZERO_IN_DATE
模式,處理除以零、零日期和日期中的零。
本節比較 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 ... SELECT
:IGNORE
不適用於陳述式的CREATE TABLE
或SELECT
部分,而是適用於插入SELECT
所產生列的資料表。會捨棄在唯一索引鍵值上與現有列重複的列。DELETE
:IGNORE
會導致 MySQL 在刪除列的過程中忽略錯誤。INSERT
:使用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 模式的錯誤。