7.1.11 服务器 SQL 模式
MySQL 服务器可以在不同的 SQL 模式下运行,并且可以根据sql_mode
系统变量的值对不同的客户端应用不同的模态。DBA 可以将全局 SQL 模式设置为与站点服务器操作要求相匹配,每个应用程序可以将其会话 SQL 模式设置为其自己的要求。
模态影响 MySQL 支持的 SQL 语法和数据验证检查。这使得在不同的环境中使用 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-mode=<
或在选项文件,如modes
>my.cnf
(Unix操作系统)或my.ini
(Windows),将SQL模式设置为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模式后创建和插入数据到分区表中可能会导致这些表的行为发生major变化,并可能导致数据丢失或损坏。强烈建议您从未更改使用自定义分区的表的SQL模式。
在复制分区表时,源服务器和副本服务器上的SQL模式不同也可能导致问题。为了获得最佳结果,请始终在源服务器和副本服务器上使用相同的服务器SQL模式。
更多信息,请见第26.6节,“分区限制和限制”。
最重要的sql_mode
值可能是:
-
该模式将语法和行为调整为更紧密地遵循标准SQL。它是组合模式列表的其中一个,位于本节末尾。
-
如果不能将值插入事务表中,就中止语句。如果是非事务表,就在单行语句或多行语句的第一行中止语句。更多详细信息请见本节后面。
-
使MySQL像传统的SQL数据库系统一样。该模式的简单描述是“插入错误值时给出错误,而不是警告”。它是组合模式列表的其中一个,位于本节末尾。
Note在启用
TRADITIONAL
模式时,INSERT
或UPDATE
语句将在错误发生时中止。如果您使用非事务存储引擎,这可能不是您想要的,因为在错误发生前已经执行的数据更改可能不会被回滚,从而导致部分完成的更新。
当本手册提到“严格模式”时,它指的是启用了STRICT_TRANS_TABLES
或STRICT_ALL_TABLES
其中一种或两种模式。
以下是所有支持的SQL模式的列表:
-
不执行完整的日期检查。只检查月份是否在1-12范围内,日期是否在1-31范围内。这可能对Web应用程序有用,该应用程序从用户处获取年、月、日三个字段,并将用户输入的值存储在数据库中,而不进行日期验证。这一模式适用于
DATE
和DATETIME
列,不适用于TIMESTAMP
列,因为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节,“Schema Object Names”中所述那样被引用。例如,因为存在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节,“Function Name Parsing and Resolution”。 -
NO_AUTO_VALUE_ON_ZERO
影响AUTO_INCREMENT
列的处理。通常,您可以通过将AUTO_INCREMENT
列插入0
或NULL
来生成下一个顺序号。NO_AUTO_VALUE_ON_ZERO
将抑制0
的这种行为,使得只有NULL
生成下一个顺序号。这个模式可以在将
0
存储在表的AUTO_INCREMENT
列中时非常有用。存储0
并不是推荐的实践方法。例如,如果使用mysqldump将表dump到文件,然后重新加载该文件,MySQL通常会在遇到0
值时生成新的序列号,从而导致dump的表内容不同于原始表。启用NO_AUTO_VALUE_ON_ZERO
在重新加载dump文件时解决这个问题。因此,mysqldump自动在输出中包含启用NO_AUTO_VALUE_ON_ZERO
的语句。 -
启用这个模式将禁用在字符串和标识符中使用反斜杠字符(
\
)作为转义字符。启用该模式时,反斜杠将变为任何其他字符一样,并且LIKE
表达式的默认转义序列将被更改为不使用转义字符。 -
在创建表时,忽略所有
INDEX DIRECTORY
和DATA DIRECTORY
指令。这项选项在复制服务器上非常有用。 -
控制在语句,如
CREATE TABLE
或ALTER TABLE
指定的存储引擎是禁用或未编译的时自动替换默认存储引擎。默认情况下,
NO_ENGINE_SUBSTITUTION
是启用的。由于存储引擎可以在运行时插件,因此 unavailable引擎将被视为同样处理:
在
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
在所有上下文中不可完全使用。请参阅第14.10节,“Cast Functions and Operators”。 -
模式
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
而不启用严格模式或 vice versa。由于
NO_ZERO_DATE
已弃用,您应该期望它在未来 MySQL 发布中被删除,并且其效果包含在严格 SQL 模式的效果中。 -
-
《
NO_ZERO_IN_DATE
》模式影响服务器是否允许年份部分为零,但月份或日期部分为零的日期(例如:'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子句引用别名表达式在选择列表中。无论是否启用
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
值的fractional seconds 部分到具有相同类型但更少fractional digits 的列时是否进行舍入或截断。默认行为是使用舍入。如果启用了该模式,截断将发生。以下是一系列语句,展示了不同情况的结果: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
模式还会使服务器在外部引用MAX(t1.b)
不能在外部查询中聚合,因为它出现在该查询的WHERE子句中。标准SQL在这种情况下要求错误。如果ANSI
模式未启用,服务器将对MAX(t1.b)
进行处理,类似于它将对MAX(t1.b)
进行处理。SELECT * FROM t1 WHERE t1.a IN (SELECT MAX(t1.b) FROM t2 WHERE ...);
-
传统
等同于STRICT_TRANS_TABLES
、STRICT_ALL_TABLES
、NO_ZERO_IN_DATE
、NO_ZERO_DATE
、ERROR_FOR_DIVISION_BY_ZERO
和NO_ENGINE_SUBSTITUTION
。
严格模式控制 MySQL 如何处理无效或缺失的数据更改语句,如INSERT
或UPDATE
。一个值可能无效的原因有多种。例如,它可能具有错误的数据类型或超出范围。一个值是缺失的,当一个新行要被插入时,但该行中没有为非空列指定的值,该列没有明确的默认值定义。 (对于一个空列,MySQL 将插入 NULL 值。) 严格模式也影响DDL 语句,如CREATE TABLE
。
如果严格模式不在 effect 中,MySQL 将插入调整后的值以处理无效或缺失的值,并生成警告(见Section 15.7.7.41, “SHOW WARNINGS 语句”)。在严格模式下,您可以使用INSERT IGNORE
或UPDATE IGNORE
。
对于不改变数据的语句,如SELECT
,严格模式下无效值将生成警告,而不是错误。
严格模式将产生错误,以尝试创建的键超过最大键长度。当严格模式不在 effect 中,这将生成警告,并将键截断到最大键长度。
严格模式不影响外键约束的检查。foreign_key_checks
可以用于该目的。 (见Section 7.1.8, “Server System Variables”。)
严格 SQL 模式在 effect 中,如果启用了STRICT_ALL_TABLES
或STRICT_TRANS_TABLES
,尽管这两个模式的效果有所不同:
-
对于事务表,启用
STRICT_ALL_TABLES
或STRICT_TRANS_TABLES
时,出现无效或缺失值的数据更改语句将引发错误。语句将被中止并回滚。 -
对于非事务表,如果在插入或更新的第一行出现错误值,语句将被中止,表格保持不变。如果语句插入或修改多行,并且错误值出现在第二行或更后行,结果取决于启用的严格模式:
-
对于
STRICT_ALL_TABLES
,MySQL返回错误并忽略剩余的行。然而,因为早期行已经被插入或更新,结果是一个部分更新。为了避免这种情况,使用单行语句,这些语句可以在不改变表格的情况下被中止。 -
对于
STRICT_TRANS_TABLES
,MySQL将无效值转换为最接近的有效值,并插入调整后的值。如果值缺失,MySQL将插入该列的隐式默认值。在任何情况下,MySQL都会生成警告,而不是错误。隐式默认值在第13.6节,“Data Type Default Values”中有描述。
-
严格模式对零除法、零日期和零日期的处理方式如下:
-
严格模式对零除法的处理包括
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'
将被允许,并且插入语句将产生警告。
-
-
严格模式对是否允许日期的处理方式如下:
-
如果严格模式未启用,零部分日期允许,并且插入操作不产生警告。
-
如果严格模式启用,零部分日期不允许,并且插入操作产生错误,除非同时使用
IGNORE
。对于INSERT IGNORE
和UPDATE IGNORE
,零部分日期将被插入为'0000-00-00'
(被认为是有效的),并且产生警告。
-
有关IGNORE
和严格 SQL 模式的更多信息,请参见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 模式可以被认为是相反的错误处理方式,但它们在一起使用时不互相取消。
MySQL 支持多个语句,其中包括可选的IGNORE
关键字。这个关键字使服务器将某些类型的错误降级为警告。对于多行语句,降低错误到警告可能使行被处理。否则,IGNORE
将语句跳到下一行,而不是中止。 (对于不可忽略的错误,错误仍然会发生, REGARDLESS OF THE 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
将忽略删除过程中的错误。 -
INSERT
:使用IGNORE
,重复的行将被忽略。将要导致数据转换错误的行将被设置为最近的有效值。 -
UPDATE
:使用IGNORE
,重复键冲突的行将不被更新。将要导致数据转换错误的行将被设置为最近的有效值。
IGNORE
关键字适用于以下忽略错误:
MySQL 服务器可以在不同的 SQL 模式下运行,并且可以根据 sql_mode
系统变量的值,对不同客户端应用不同的模式。
例如,在非严格 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节,“Server SQL Modes”。
严格 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 模式。