MySQL 服务器可以在不同的 SQL 模式下操作,并且可以根据 sql_mode
系统变量的值对不同的客户端应用不同的模式。DBA 可以将全局 SQL 模式设置为匹配站点服务器操作要求,每个应用程序可以将其会话 SQL 模式设置为其自己的要求。
模式影响 MySQL 支持的 SQL 语法和执行的数据验证检查。这使得 MySQL 在不同的环境中使用变得更容易,并且可以与其他数据库服务器一起使用。
关于 MySQL 服务器 SQL 模式的常见问题的答案,请参阅 第 A.3 节,“MySQL 8.3 FAQ:服务器 SQL 模式”。
在使用 InnoDB
表时,也请考虑 innodb_strict_mode
系统变量。它为 InnoDB
表启用了附加的错误检查。
MySQL 8.3 的默认 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)。modes
是一个以逗号分隔的不同模式的列表。要明确清除 SQL 模式,请将其设置为空字符串,使用 --sql-mode=""
在命令行上,或者在选项文件中。
MySQL 安装程序可能会在安装过程中配置 SQL 模式。
如果 SQL 模式不同于默认值或您期望的值,请检查启动时读取的选项文件中的设置。
要在运行时更改 SQL 模式,请设置全局或会话 sql_mode
系统变量,使用 SET
语句:
SET GLOBAL sql_mode = 'modes';
SET SESSION sql_mode = 'modes';
设置全局变量需要 SYSTEM_VARIABLES_ADMIN
权限(或已弃用的 SUPER
权限),并影响从那时起连接的所有客户端。设置会话变量仅影响当前客户端。每个客户端可以随时更改其会话 sql_mode
值。
要确定当前的全局或会话 sql_mode
设置,请选择其值:
SELECT @@GLOBAL.sql_mode;
SELECT @@SESSION.sql_mode;
SQL 模式和用户定义的分区。
在复制分区表时,源和副本上的不同 SQL 模式也可能导致问题。为了获得最佳结果,应该始终在源和副本上使用相同的服务器 SQL 模式。
有关更多信息,请参阅 第 26.6 节,“分区限制和限制”。
最重要的 sql_mode
值可能是这些:
-
该模式更改语法和行为,以更好地符合标准 SQL。这是本节末尾列出的特殊 组合模式 之一。
-
如果无法将值插入事务表中,abort 语句。对于非事务表,如果值出现在单行语句或多行语句的第一行中,abort 语句。稍后在本节中将提供更多详细信息。
-
使 MySQL 行为像一个 “传统” SQL 数据库系统。该模式的简单描述是 “出现错误时给出错误而不是警告” 当插入不正确的值到列中时。这是本节末尾列出的特殊 组合模式 之一。
Note启用
TRADITIONAL
模式后,INSERT
或UPDATE
在出现错误时abort。如果您使用的是非事务存储引擎,这可能不是您想要的,因为在错误之前的数据更改可能不会回滚,导致 “部分完成” 更新。
当本手册提到 “严格模式,” 它指的是启用了 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 引号
后,无法使用双引号来引用字符串,因为它们被解释为标识符。 -
该
零除错误
模式影响零除处理,包括MOD(
。对于数据更改操作(N
,0)INSERT
、UPDATE
),其效果还取决于是否启用了严格 SQL 模式。-
如果未启用该模式,零除将插入
NULL
并不产生警告。 -
如果启用该模式,零除将插入
NULL
并产生警告。 -
如果启用该模式和严格模式,零除将产生错误,除非也给出了
IGNORE
。对于INSERT IGNORE
和UPDATE IGNORE
,零除将插入NULL
并产生警告。
对于
SELECT
,零除将返回NULL
。启用零除错误
将产生警告,无论是否启用了严格模式。零除错误
已弃用。零除错误
不是严格模式的一部分,但应该与严格模式一起使用,默认情况下启用。 如果启用零除错误
而不启用严格模式,或者反之亦然,将产生警告。由于
零除错误
已弃用,因此您应该期望在未来 MySQL 版本中将其删除作为单独的模式名称,并将其效果包含在严格 SQL 模式的效果中。 -
-
NOT 运算符的优先级使得表达式如
NOT a BETWEEN b AND c
被解析为NOT (a BETWEEN b AND c)
。在某些旧版本的 MySQL 中,该表达式被解析为(NOT a) BETWEEN b AND c
。可以通过启用高 NOT 优先级
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 节“Schema 对象名称” 中所述那样引用。例如,因为存在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)
该
忽略空格
SQL 模式仅适用于内置函数,不适用于可加载函数或存储函数。无论是否启用忽略空格
,都可以在可加载函数或存储函数名称后面添加空格。有关
忽略空格
的进一步讨论,请参阅 第 11.2.5 节“函数名称解析和解析”。 -
不自动将零作为默认值
影响AUTO_INCREMENT
列的处理方式。通常,您可以通过将NULL
或0
插入该列来生成下一个序列号。不自动将零作为默认值
suppresses 这种行为对于0
,因此只有NULL
生成下一个序列号。这种模式在
0
已经存储在表的AUTO_INCREMENT
列中时非常有用。(存储0
并不是一个推荐的做法。)例如,如果您使用 mysqldump 转储表,然后重新加载它,MySQL 通常会在遇到0
值时生成新的序列号,从而导致表的内容与转储的表不同。启用不自动将零作为默认值
之前重新加载转储文件可以解决这个问题。出于这个原因,mysqldump 自动在其输出中包含一条启用不自动将零作为默认值
的语句。 -
启用该模式将禁用反斜杠字符 (
\
) 作为字符串和标识符中的转义字符。启用该模式后,反斜杠变成了一个普通字符,LIKE
表达式的默认转义序列也将更改,以便不使用转义字符。 -
在创建表时,忽略所有
INDEX DIRECTORY
和DATA DIRECTORY
指令。这项选项在副本服务器上非常有用。 -
控制在语句中指定的存储引擎不可用或未编译时的自动替换,例如
CREATE TABLE
或ALTER TABLE
。默认情况下,
不替换存储引擎
是启用的。因为存储引擎可以在运行时动态加载,Unavailable 引擎被视为同一种情况:
如果
不替换存储引擎
被禁用,对于CREATE TABLE
,默认引擎将被使用,并在所需引擎不可用时发出警告。对于ALTER TABLE
,警告将被发出,表将不被更改。如果
不替换存储引擎
被启用,错误将发生,表将不被创建或更改,如果所需引擎不可用。 -
在整数值之间的减法运算中,其中一个值的类型为
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)'
如果启用了
不使用无符号减法
SQL 模式,结果将是负数:mysql> SET sql_mode = 'NO_UNSIGNED_SUBTRACTION'; mysql> SELECT CAST(0 AS UNSIGNED) - 1; +-------------------------+ | CAST(0 AS UNSIGNED) - 1 | +-------------------------+ | -1 | +-------------------------+
如果这种操作的结果用于更新
UNSIGNED
整数列,结果将被截断到列类型的最大值,或者如果启用了不使用无符号减法
,结果将被截断到 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
并不是在所有情况下都可用的。参见 第 14.10 节,“Cast 函数和操作符”。 -
模式
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
影响服务器是否允许日期,其中年份部分非零,但月份或日部分为零。(该模式影响日期,如'2010-00-01'
或'2010-01-00'
,但不影响'0000-00-00'
。要控制服务器是否允许'0000-00-00'
,请使用NO_ZERO_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
子句中引用别名表达式。无论ONLY_FULL_GROUP_BY
是否启用,HAVING
子句都可以引用别名。有关更多讨论和示例,请参见第14.19.3节,“MySQL Handling of GROUP BY”。
-
默认情况下,在检索时从
CHAR
列值中删除尾随空格。如果启用PAD_CHAR_TO_FULL_LENGTH
,则不删除尾随空格,并将检索的CHAR
值填充到其全长。此模式不适用于VARCHAR
列,对于这些列,尾随空格在检索时保留。NotePAD_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
具有外部引用
不能在外部查询中聚合。这种查询是: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.44 节,“SHOW WARNINGS 语句”)。在严格模式下,可以使用 INSERT IGNORE
或 UPDATE IGNORE
产生这种行为。
对于不更改数据的语句,如 SELECT
,严格模式下无效值生成警告,而不是错误。
严格模式会在尝试创建超出最大键长的键时生成错误。当严格模式不生效时,这将生成警告并将键截断到最大键长。
严格模式不影响外键约束的检查。foreign_key_checks
可以用于该目的。(参见 第 7.1.8 节,“服务器系统变量”。)
严格 SQL 模式生效,如果启用了 STRICT_ALL_TABLES
或 STRICT_TRANS_TABLES
,尽管这两种模式的效果略有不同:
-
对于事务表,如果数据更改语句中的值无效或缺失时,会出现错误,前提是启用了
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'
将被允许,并且插入操作将产生警告。
-
-
严格模式影响服务器是否允许日期中的零部分(例如
'2010-00-01'
或'2010-01-00'
):-
如果未启用严格模式,日期中的零部分将被允许,并且插入操作将不产生警告。
-
如果启用了严格模式,日期中的零部分将不被允许,并且插入操作将产生错误,除非同时指定了
IGNORE
。对于INSERT IGNORE
和UPDATE IGNORE
,日期中的零部分将被插入为'0000-00-00'
(这将被视为有效日期),并且插入操作将产生警告。
-
有关严格模式与IGNORE
关键字的更多信息,请参阅比较 IGNORE 关键字和严格 SQL 模式。
严格模式影响除零、零日期和日期中的零的处理方式,结合ERROR_FOR_DIVISION_BY_ZERO
、NO_ZERO_DATE
和NO_ZERO_IN_DATE
模式。
本节比较了语句执行中的 IGNORE 关键字(将错误降级为警告)和严格 SQL 模式(将警告升级为错误)的效果。它描述了它们影响的语句、错误和应用场景。
以下表格对比了语句行为的摘要,当默认情况下产生错误与警告。例如,默认情况下产生错误的是将NULL
插入到NOT NULL
列中。例如,默认情况下产生警告的是将错误数据类型的值插入到列中(例如,将字符串'abc'
插入到整数列中)。
Operational Mode | When Statement Default is Error | When Statement Default is Warning |
---|---|---|
Without IGNORE or strict SQL mode |
错误 | 警告 |
With IGNORE |
警告 | 警告(与不使用IGNORE 或严格SQL模式相同) |
With strict SQL mode | 错误(与不使用IGNORE 或严格SQL模式相同) |
错误 |
With IGNORE and strict SQL mode |
警告 | 警告 |
从表格中可以得出结论,即当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
适用于以下可忽略的错误:
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
系统变量可能的设置,请参阅 第 7.1.11 节,“服务器 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 模式适用的错误不在上述列表中。