Documentation Home
MySQL 8.3 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 40.8Mb
PDF (A4) - 40.9Mb
Man Pages (TGZ) - 294.0Kb
Man Pages (Zip) - 409.0Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb
Excerpts from this Manual

7.1.11 服务器 SQL 模式

MySQL 服务器可以在不同的 SQL 模式下操作,并且可以根据 sql_mode 系统变量的值对不同的客户端应用不同的模式。DBA 可以将全局 SQL 模式设置为匹配站点服务器操作要求,每个应用程序可以将其会话 SQL 模式设置为其自己的要求。

模式影响 MySQL 支持的 SQL 语法和执行的数据验证检查。这使得 MySQL 在不同的环境中使用变得更容易,并且可以与其他数据库服务器一起使用。

关于 MySQL 服务器 SQL 模式的常见问题的答案,请参阅 第 A.3 节,“MySQL 8.3 FAQ:服务器 SQL 模式”

在使用 InnoDB 表时,也请考虑 innodb_strict_mode 系统变量。它为 InnoDB 表启用了附加的错误检查。

设置 SQL 模式

MySQL 8.3 的默认 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)。modes 是一个以逗号分隔的不同模式的列表。要明确清除 SQL 模式,请将其设置为空字符串,使用 --sql-mode="" 在命令行上,或者在选项文件中。

Note

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;
Important

SQL 模式和用户定义的分区。 在创建和插入数据到分区表后更改服务器 SQL 模式可能会导致这些表的行为发生重大变化,并可能导致数据丢失或损坏。强烈建议您在创建使用用户定义的分区表后不要更改 SQL 模式。

在复制分区表时,源和副本上的不同 SQL 模式也可能导致问题。为了获得最佳结果,应该始终在源和副本上使用相同的服务器 SQL 模式。

有关更多信息,请参阅 第 26.6 节,“分区限制和限制”

最重要的 SQL 模式

最重要的 sql_mode 值可能是这些:

  • ANSI

    该模式更改语法和行为,以更好地符合标准 SQL。这是本节末尾列出的特殊 组合模式 之一。

  • STRICT_TRANS_TABLES

    如果无法将值插入事务表中,abort 语句。对于非事务表,如果值出现在单行语句或多行语句的第一行中,abort 语句。稍后在本节中将提供更多详细信息。

  • TRADITIONAL

    使 MySQL 行为像一个 传统 SQL 数据库系统。该模式的简单描述是 出现错误时给出错误而不是警告 当插入不正确的值到列中时。这是本节末尾列出的特殊 组合模式 之一。

    Note

    启用 TRADITIONAL 模式后,INSERTUPDATE 在出现错误时abort。如果您使用的是非事务存储引擎,这可能不是您想要的,因为在错误之前的数据更改可能不会回滚,导致 部分完成 更新。

当本手册提到 严格模式, 它指的是启用了 STRICT_TRANS_TABLESSTRICT_ALL_TABLES 的模式。

完整的 SQL 模式列表

以下列表描述了所有支持的 SQL 模式:

  • ALLOW_INVALID_DATES

    不执行完整的日期检查。仅检查月份在 1 到 12 之间,日在 1 到 31 之间。这可能对 Web 应用程序有用,该应用程序从三个不同的字段中获取年、月和日,并存储用户插入的确切值,而不进行日期验证。这适用于 DATEDATETIME 列,但不适用于 TIMESTAMP 列,该列始终需要有效的日期。

    禁用 ALLOW_INVALID_DATES 后,服务器要求月份和日值合法,而不仅仅是在 1 到 12 和 1 到 31 之间。禁用严格模式时,非法日期例如 '2004-04-31' 将被转换为 '0000-00-00' 并生成警告。启用严格模式时,非法日期将生成错误。要允许这些日期,启用 ALLOW_INVALID_DATES

  • ANSI 引号

    " 视为标识符引号字符(类似于 ` 引号字符),而不是字符串引号字符。您仍然可以使用 ` 引号标识符,即使启用了该模式。启用 ANSI 引号 后,无法使用双引号来引用字符串,因为它们被解释为标识符。

  • 零除错误

    零除错误 模式影响零除处理,包括 MOD(N,0)。对于数据更改操作(INSERTUPDATE),其效果还取决于是否启用了严格 SQL 模式。

    • 如果未启用该模式,零除将插入 NULL 并不产生警告。

    • 如果启用该模式,零除将插入 NULL 并产生警告。

    • 如果启用该模式和严格模式,零除将产生错误,除非也给出了 IGNORE。对于 INSERT IGNOREUPDATE IGNORE,零除将插入 NULL 并产生警告。

    对于 SELECT,零除将返回 NULL。启用 零除错误 将产生警告,无论是否启用了严格模式。

    零除错误 已弃用。零除错误 不是严格模式的一部分,但应该与严格模式一起使用,默认情况下启用。 如果启用 零除错误 而不启用严格模式,或者反之亦然,将产生警告。

    由于 零除错误 已弃用,因此您应该期望在未来 MySQL 版本中将其删除作为单独的模式名称,并将其效果包含在严格 SQL 模式的效果中。

  • 高 NOT 优先级

    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 列的处理方式。通常,您可以通过将 NULL0 插入该列来生成下一个序列号。不自动将零作为默认值 suppresses 这种行为对于 0,因此只有 NULL 生成下一个序列号。

    这种模式在 0 已经存储在表的 AUTO_INCREMENT 列中时非常有用。(存储 0 并不是一个推荐的做法。)例如,如果您使用 mysqldump 转储表,然后重新加载它,MySQL 通常会在遇到 0 值时生成新的序列号,从而导致表的内容与转储的表不同。启用 不自动将零作为默认值 之前重新加载转储文件可以解决这个问题。出于这个原因,mysqldump 自动在其输出中包含一条启用 不自动将零作为默认值 的语句。

  • 不使用反斜杠转义

    启用该模式将禁用反斜杠字符 (\) 作为字符串和标识符中的转义字符。启用该模式后,反斜杠变成了一个普通字符,LIKE 表达式的默认转义序列也将更改,以便不使用转义字符。

  • 不在创建表时使用目录

    在创建表时,忽略所有 INDEX DIRECTORYDATA DIRECTORY 指令。这项选项在副本服务器上非常有用。

  • 不替换存储引擎

    控制在语句中指定的存储引擎不可用或未编译时的自动替换,例如 CREATE TABLEALTER 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

    模式 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 影响服务器是否允许日期,其中年份部分非零,但月份或日部分为零。(该模式影响日期,如 '2010-00-01''2010-01-00',但不影响 '0000-00-00'。要控制服务器是否允许 '0000-00-00',请使用 NO_ZERO_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 列。

    MySQL扩展了标准SQL,允许在HAVING子句中引用别名表达式。无论ONLY_FULL_GROUP_BY是否启用,HAVING子句都可以引用别名。

    有关更多讨论和示例,请参见第14.19.3节,“MySQL Handling of GROUP BY”

  • PAD_CHAR_TO_FULL_LENGTH

    默认情况下,在检索时从CHAR列值中删除尾随空格。如果启用PAD_CHAR_TO_FULL_LENGTH,则不删除尾随空格,并将检索的CHAR值填充到其全长。此模式不适用于VARCHAR列,对于这些列,尾随空格在检索时保留。

    Note

    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.44 节,“SHOW WARNINGS 语句”)。在严格模式下,可以使用 INSERT IGNOREUPDATE IGNORE 产生这种行为。

对于不更改数据的语句,如 SELECT,严格模式下无效值生成警告,而不是错误。

严格模式会在尝试创建超出最大键长的键时生成错误。当严格模式不生效时,这将生成警告并将键截断到最大键长。

严格模式不影响外键约束的检查。foreign_key_checks 可以用于该目的。(参见 第 7.1.8 节,“服务器系统变量”。)

严格 SQL 模式生效,如果启用了 STRICT_ALL_TABLESSTRICT_TRANS_TABLES,尽管这两种模式的效果略有不同:

  • 对于事务表,如果数据更改语句中的值无效或缺失时,会出现错误,前提是启用了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'将被允许,并且插入操作将产生警告。

  • 严格模式影响服务器是否允许日期中的零部分(例如'2010-00-01''2010-01-00'):

    • 如果未启用严格模式,日期中的零部分将被允许,并且插入操作将不产生警告。

    • 如果启用了严格模式,日期中的零部分将不被允许,并且插入操作将产生错误,除非同时指定了IGNORE。对于INSERT IGNOREUPDATE IGNORE,日期中的零部分将被插入为'0000-00-00'(这将被视为有效日期),并且插入操作将产生警告。

有关严格模式与IGNORE关键字的更多信息,请参阅比较 IGNORE 关键字和严格 SQL 模式

严格模式影响除零、零日期和日期中的零的处理方式,结合ERROR_FOR_DIVISION_BY_ZERONO_ZERO_DATENO_ZERO_IN_DATE模式。

IGNORE 关键字和严格 SQL 模式的比较

本节比较了语句执行中的 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 NULLid,尝试将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忽略删除行过程中的错误。

  • INSERTIGNORE使重复唯一键值的行被丢弃。将值设置为可能导致数据转换错误的值时,将其设置为最近的有效值。

    对于分区表,如果找不到匹配的分区,IGNORE将导致插入操作失败,静默地处理包含未匹配值的行。

  • LOAD DATALOAD XMLIGNORE使重复唯一键值的行被丢弃。

  • UPDATEIGNORE使重复唯一键值的行不被更新。将值设置为可能导致数据转换错误的值时,将其设置为最近的有效值。

关键字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
Note

由于 MySQL 的继续开发定义了新的错误,因此可能存在严格 SQL 模式适用的错误不在上述列表中。