MySQL 伺服器可以在不同的 SQL 模式下運作,並且可以根據 sql_mode
系統變數的值,為不同的用戶端應用這些模式。DBA 可以設定全域 SQL 模式以符合站點伺服器運作要求,而每個應用程式都可以設定其工作階段 SQL 模式以符合其自身的要求。
模式會影響 MySQL 支援的 SQL 語法以及其執行的資料驗證檢查。這使得在不同的環境中使用 MySQL,以及將 MySQL 與其他資料庫伺服器一起使用變得更容易。
如需關於 MySQL 中伺服器 SQL 模式的常見問題解答,請參閱 第 A.3 節, “MySQL 8.4 FAQ:伺服器 SQL 模式”。
在使用 InnoDB
表格時,也請考慮 innodb_strict_mode
系統變數。它會為 InnoDB
表格啟用額外的錯誤檢查。
MySQL 8.4 中的預設 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 的範圍內。這對於在三個不同欄位中取得年、月和日,並在不進行日期驗證的情況下,確切儲存使用者插入內容的 Web 應用程式可能很有用。此模式適用於
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
欄位的非聚合欄位的查詢。MySQL 對標準 SQL 的擴展允許在
HAVING
子句中引用選取清單中的別名表達式。HAVING
子句可以引用別名,無論是否啟用ONLY_FULL_GROUP_BY
。如需其他討論和範例,請參閱 第 14.19.3 節,「MySQL 的 GROUP BY 處理」。
預設情況下,從
CHAR
欄位值中擷取時,會修剪尾隨空格。如果啟用PAD_CHAR_TO_FULL_LENGTH
,則不會發生修剪,且擷取的CHAR
值會填補到其完整長度。此模式不適用於VARCHAR
欄位,對於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 | +------+------------+
另請參閱 第 13.2.6 節,「時間值中的小數秒」。
以下特殊模式是作為前述清單中模式值的組合簡寫而提供的。
等效於
REAL_AS_FLOAT
、PIPES_AS_CONCAT
、ANSI_QUOTES
、IGNORE_SPACE
和ONLY_FULL_GROUP_BY
。ANSI
模式也會導致伺服器針對查詢傳回錯誤,其中具有外部參照
的集合函數S
(outer_ref
)S
無法在已解析外部參照的外部查詢中進行聚合。這是一個這樣的查詢。SELECT * FROM t1 WHERE t1.a IN (SELECT MAX(t1.b) FROM t2 WHERE ...);
在此,
MAX(t1.b)
無法在外部查詢中聚合,因為它出現在該查詢的WHERE
子句中。標準 SQL 在這種情況下需要錯誤。如果未啟用ANSI
模式,則伺服器會以與解釋
相同的方式處理此類查詢中的S
(const
)
。S
(outer_ref
)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 模式。