文档首页
MySQL 8.4 参考手册
相关文档 下载本手册
PDF (US Ltr) - 39.9Mb
PDF (A4) - 40.0Mb
手册页 (TGZ) - 258.5Kb
手册页 (Zip) - 365.5Kb
信息 (Gzip) - 4.0Mb
信息 (Zip) - 4.0Mb


MySQL 8.4 参考手册  /  ...  /  服务器 SQL 模式

7.1.11 服务器 SQL 模式

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

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

有关 MySQL 中服务器 SQL 模式的常见问题的答案,请参见 第 A.3 节,“MySQL 8.4 常见问题解答:服务器 SQL 模式”

使用 InnoDB 表时,还要考虑 innodb_strict_mode 系统变量。它为 InnoDB 表启用了额外的错误检查。

设置 SQL 模式

MySQL 8.4 中的默认 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))中使用 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 模式

最重要的 sql_mode 值可能是以下这些

  • ANSI

    此模式会更改语法和行为,使其更符合标准 SQL。它是本节末尾列出的特殊 组合模式 之一。

  • STRICT_TRANS_TABLES

    如果一个值不能按原样插入到事务性表中,则中止该语句。对于非事务性表,如果该值出现在单行语句或多行语句的第一行中,则中止该语句。本节稍后将对此进行详细介绍。

  • TRADITIONAL

    使 MySQL 表现得像“传统”SQL 数据库系统。对这种模式的简单描述是,在将不正确的值插入列时“给出错误而不是警告”。它是本节末尾列出的特殊组合模式之一。

    注意

    启用TRADITIONAL模式后,INSERTUPDATE 会在发生错误时立即中止。如果您使用的是非事务性存储引擎,这可能不是您想要的,因为在错误发生之前所做的数据更改可能不会回滚,从而导致更新“部分完成”。

当本手册提到“严格模式”时,它指的是启用了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_QUOTES

    " 视为标识符引号字符(类似于 ` 引号字符),而不是字符串引号字符。启用此模式后,您仍然可以使用 ` 为标识符加引号。启用 ANSI_QUOTES 后,您不能使用双引号为文字字符串加引号,因为它们会被解释为标识符。

  • ERROR_FOR_DIVISION_BY_ZERO

    ERROR_FOR_DIVISION_BY_ZERO 模式会影响除以零的处理方式,其中包括 MOD(N,0)。对于数据更改操作(INSERTUPDATE),其影响还取决于是否启用了严格 SQL 模式。

    • 如果未启用此模式,则除以零将插入 NULL 并且不会产生警告。

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

    • 如果同时启用了此模式和严格模式,则除以零会产生错误,除非还给出了 IGNORE。对于 INSERT IGNOREUPDATE 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 模式的效果中。

  • HIGH_NOT_PRECEDENCE

    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
  • IGNORE_SPACE

    允许函数名称和 ( 字符之间存在空格。这会导致内置函数名称被视为保留字。因此,与函数名称相同的标识符必须像 第 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

    NO_AUTO_VALUE_ON_ZERO 会影响 AUTO_INCREMENT 列的处理方式。通常,您可以通过在其中插入 NULL0 来生成该列的下一个序列号。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 的语句。

  • NO_BACKSLASH_ESCAPES

    启用此模式将禁用反斜杠字符 (\) 在字符串和标识符中用作转义字符。启用此模式后,反斜杠将成为与任何其他字符一样的普通字符,并且 LIKE 表达式的默认转义序列将更改为不使用转义字符。

  • NO_DIR_IN_CREATE

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

  • NO_ENGINE_SUBSTITUTION

    当诸如 CREATE TABLEALTER TABLE 之类的语句指定了已禁用或未编译的存储引擎时,控制默认存储引擎的自动替换。

    默认情况下,NO_ENGINE_SUBSTITUTION 处于启用状态。

    因为存储引擎可以在运行时可插拔,所以不可用的引擎的处理方式相同

    如果禁用 NO_ENGINE_SUBSTITUTION,则对于 CREATE TABLE,将使用默认引擎,并且如果所需的引擎不可用,则会发出警告。对于 ALTER TABLE,会发出警告,并且不会更改表。

    如果启用 NO_ENGINE_SUBSTITUTION,则如果所需的引擎不可用,则会发生错误,并且不会创建或更改表。

  • NO_UNSIGNED_SUBTRACTION

    默认情况下,整数值之间的减法(其中一个值为 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

    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 模式会影响服务器是否允许年份部分不为零但月份或日期部分为 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 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 列的函数依赖项(由其唯一确定)的非聚合列的查询。

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

    有关其他讨论和示例,请参见 第 14.19.3 节“MySQL 处理 GROUP BY”

  • PAD_CHAR_TO_FULL_LENGTH

    默认情况下,检索时会从 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)
  • 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)中的无效值或缺失值。值可能由于多种原因而无效。例如,它可能具有错误的数据类型,或者可能超出范围。当要插入的新行不包含没有显式 DEFAULT 子句的非 NULL 列的值时,该值将丢失。(对于 NULL 列,如果缺少该值,则插入 NULL。)严格模式还会影响 DDL 语句,如 CREATE TABLE

如果未启用严格模式,MySQL 会为无效值或缺失值插入调整后的值,并生成警告(请参见 第 15.7.7.41 节“SHOW WARNINGS 语句”)。在严格模式下,您可以使用 INSERT IGNOREUPDATE IGNORE 生成此行为。

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

严格模式会在尝试创建超过最大密钥长度的密钥时产生错误。如果未启用严格模式,则会导致警告并将密钥截断为最大密钥长度。

严格模式不会影响是否检查外键约束。可以使用 foreign_key_checks 来实现这一点。(请参见 第 7.1.8 节“服务器系统变量”。)

如果启用了 STRICT_ALL_TABLESSTRICT_TRANS_TABLES,则严格 SQL 模式将生效,尽管这些模式的效果略有不同

  • 对于事务性表,如果启用了 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',并且插入会产生警告。

  • 严格模式会影响服务器是否允许日期的年份部分不为零,但月份或日期部分为 0(例如 '2010-00-01''2010-01-00'

    • 如果未启用严格模式,则允许日期的某些部分为零,并且插入不会产生警告。

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

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

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

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

本节比较了 IGNORE 关键字(将错误降级为警告)和严格 SQL 模式(将警告升级为错误)对语句执行的影响。它描述了它们影响哪些语句,以及它们适用于哪些错误。

下表总结了在默认情况下产生错误与产生警告时语句行为的比较。默认情况下产生错误的示例是将 NULL 插入 NOT NULL 列。默认情况下产生警告的示例是将错误数据类型的 value 插入列(例如将字符串 '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 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 在删除行的过程中忽略错误。

  • INSERT:使用 IGNORE 时,将在唯一键值上与现有行重复的行丢弃。设置为会导致数据转换错误的值的行将设置为最接近的有效值。

    对于找不到与给定值匹配的分区的表,IGNORE 会导致插入操作针对包含不匹配值的行静默失败。

  • LOAD DATALOAD XML:使用 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 模式适用于以下错误,这些错误表示一类错误,其中输入值无效或缺失。如果值的数据类型与列不匹配或可能超出范围,则该值无效。如果要插入的新行不包含其定义中没有显式 DEFAULT 子句的 NOT NULL 列的值,则该值缺失。

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 模式适用的错误。