文档首页
MySQL 9.0 参考手册
相关文档 下载本手册
PDF (US Ltr) - 40.0Mb
PDF (A4) - 40.1Mb
手册页 (TGZ) - 258.2Kb
手册页 (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


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

7.1.11 服务器 SQL 模式

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

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

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

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

设置 SQL 模式

MySQL 9.0 中的默认 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 会抑制这种行为,因为 0NULL 会生成下一个序列号。

    如果表 AUTO_INCREMENT 列中已存储 0,则此模式可能很有用。(顺便说一下,存储 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

    拒绝查询,其中 select 列表、HAVING 条件或 ORDER BY 列表引用未聚合的列,这些列既未在 GROUP BY 子句中命名,也未在功能上依赖于(由 GROUP BY 列唯一确定)。

    MySQL 对标准 SQL 的扩展允许在 HAVING 子句中引用 select 列表中的别名表达式。无论是否启用了 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 模式。有关详细信息,请参见 严格的 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。)严格模式还会影响 CREATE TABLE 之类的 DDL 语句。

如果未生效严格模式,则 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',并且插入会产生警告。

  • 严格模式影响服务器是否允许年部分不为零但月部分或日部分为零的日期(如'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列中。当默认情况下产生警告的示例是将错误的数据类型的值插入列中(例如,将字符串'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 模式适用于以下错误,这些错误代表一类错误,其中输入值无效或缺失。如果值具有错误的列数据类型或可能超出范围,则该值无效。如果要插入的新行不包含具有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 模式也适用于这些错误。