### 5.1.11 服务器 SQL 模式

[](<>)

MySQL 服务器可以运行在不同的 SQL 模式下，并且可以针对不同的客户端以不同的方式应用这些模式，具体取决于[`sql_mode`](server-system-variables.html#sysvar_sql_mode)系统变量。DBA 可以设置全局 SQL 模式以匹配站点服务器操作要求，并且每个应用程序都可以根据自己的要求设置其会话 SQL 模式。

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

-   [设置 SQL 模式](sql-mode.html#sql-mode-setting)

-   [最重要的 SQL 模式](sql-mode.html#sql-mode-important)

-   [SQL 模式的完整列表](sql-mode.html#sql-mode-full)

-   [组合 SQL 模式](sql-mode.html#sql-mode-combo)

-   [严格的 SQL 模式](sql-mode.html#sql-mode-strict)

-   [IGNORE 关键字与严格 SQL 模式的比较](sql-mode.html#ignore-strict-comparison)

    有关 MySQL 中服务器 SQL 模式的常见问题的答案，请参阅[第 A.3 节，“MySQL 8.0 常见问题解答：服务器 SQL 模式”](faqs-sql-modes.html).

    工作时`InnoDB`表，还要考虑[`innodb_strict_mode`](innodb-parameters.html#sysvar_innodb_strict_mode)系统变量。它启用了额外的错误检查`InnoDB`表。

#### 设置 SQL 模式

MySQL 8.0 中的默认 SQL 模式包括以下模式：[`ONLY_FULL_GROUP_BY`](sql-mode.html#sqlmode_only_full_group_by),[`STRICT_TRANS_TABLES`](sql-mode.html#sqlmode_strict_trans_tables),[`NO_ZERO_IN_DATE`](sql-mode.html#sqlmode_no_zero_in_date),[`NO_ZERO_DATE`](sql-mode.html#sqlmode_no_zero_date),[`ERROR_FOR_DIVISION_BY_ZERO`](sql-mode.html#sqlmode_error_for_division_by_zero)， 和[`NO_ENGINE_SUBSTITUTION`](sql-mode.html#sqlmode_no_engine_substitution).

要在服务器启动时设置 SQL 模式，请使用[`--sql-mode="*`模式`*"`](server-options.html#option_mysqld_sql-mode)命令行上的选项，或[`sql-mode="*`模式`*"`](server-options.html#option_mysqld_sql-mode)在选项文件中，例如`我的.cnf`（Unix 操作系统）或`我的.ini`（视窗）。*`模式`*是用逗号分隔的不同模式的列表。要显式清除 SQL 模式，请将其设置为空字符串，使用[`--sql-mode=""`](server-options.html#option_mysqld_sql-mode)在命令行上，或[`sql-mode=""`](server-options.html#option_mysqld_sql-mode)在选项文件中。

笔记

MySQL 安装程序可能会在安装过程中配置 SQL 模式。

如果 SQL 模式与默认模式或您期望的不同，请检查服务器在启动时读取的选项文件中的设置。

要在运行时更改 SQL 模式，请设置全局或会话[`sql_mode`](server-system-variables.html#sysvar_sql_mode)系统变量使用[`放`](set-variable.html)陈述：

```
SET GLOBAL sql_mode = 'modes';
SET SESSION sql_mode = 'modes';
```

设置`全球的`变量需要[`SYSTEM_VARIABLES_ADMIN`](privileges-provided.html#priv_system-variables-admin)特权（或已弃用的[`极好的`](privileges-provided.html#priv_super)特权）并影响从那时起连接的所有客户端的操作。设置`会议`变量只影响当前客户端。每个客户端都可以更改其会话[`sql_mode`](server-system-variables.html#sysvar_sql_mode)任何时候的价值。

确定当前的全局或会话[`sql_mode`](server-system-variables.html#sysvar_sql_mode)设置，选择它的值：

```
SELECT @@GLOBAL.sql_mode;
SELECT @@SESSION.sql_mode;
```

重要的

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

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

有关详细信息，请参阅[第 24.6 节，“分区的限制和限制”](partitioning-limitations.html).

#### 最重要的 SQL 模式

最重要的[`sql_mode`](server-system-variables.html#sysvar_sql_mode)值可能是这些：

-   [](<>) [](<>) [`ANSI`](sql-mode.html#sqlmode_ansi)

    此模式更改语法和行为以更符合标准 SQL。它是一种特殊的[组合模式](sql-mode.html#sql-mode-combo)在本节末尾列出。

-   [](<>) [](<>) [`STRICT_TRANS_TABLES`](sql-mode.html#sqlmode_strict_trans_tables)

    如果无法将给定的值插入到事务表中，则中止该语句。对于非事务性表，如果值出现在单行语句或多行语句的第一行中，则中止语句。本节稍后将提供更多详细信息。

-   [](<>) [](<>) [`传统的`](sql-mode.html#sqlmode_traditional)

    让 MySQL 表现得像一个“传统”的 SQL 数据库系统。这种模式的一个简单描述是在向列中插入不正确的值时“给出错误而不是警告”。它是一种特殊的[组合模式](sql-mode.html#sql-mode-combo)在本节末尾列出。

    笔记

    和[`传统的`](sql-mode.html#sqlmode_traditional)模式启用，一个[`插入`](insert.html)要么[`更新`](update.html)一旦发生错误就中止。如果您使用的是非事务性存储引擎，这可能不是您想要的，因为在错误之前所做的数据更改可能不会回滚，从而导致“部分完成”更新。

[](<>)[](<>)

当本手册提及“严格模式”时，它是指一种或两种模式[`STRICT_TRANS_TABLES`](sql-mode.html#sqlmode_strict_trans_tables)要么[`STRICT_ALL_TABLES`](sql-mode.html#sqlmode_strict_all_tables)启用。

#### SQL 模式的完整列表

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

-   [](<>) [`ALLOW_INVALID_DATES`](sql-mode.html#sqlmode_allow_invalid_dates)

    [](<>)[](<>)

    不要对日期进行全面检查。仅检查月份是否在 1 到 12 的范围内，日期是否在 1 到 31 的范围内。这对于在三个不同字段中获取年、月和日并准确存储用户内容的 Web 应用程序可能很有用插入，没有日期验证。该模式适用于[`日期`](datetime.html)和[`约会时间`](datetime.html)列。它不适用[`时间戳`](datetime.html)列，始终需要有效日期。

    和[`ALLOW_INVALID_DATES`](sql-mode.html#sqlmode_allow_invalid_dates)禁用时，服务器要求月份和日期值是合法的，而不仅仅是分别在 1 到 12 和 1 到 31 的范围内。在禁用严格模式的情况下，无效日期，例如`'2004-04-31'`被转换为`'0000-00-00'`并生成警告。启用严格模式后，无效日期会产生错误。要允许此类日期，请启用[`ALLOW_INVALID_DATES`](sql-mode.html#sqlmode_allow_invalid_dates).

-   [](<>) [`ANSI_QUOTES`](sql-mode.html#sqlmode_ansi_quotes)

    [](<>)[](<>)

    对待`"`作为标识符引号字符（如`引号字符）而不是字符串引号字符。你仍然可以使用`引用启用此模式的标识符。和[`ANSI_QUOTES`](sql-mode.html#sqlmode_ansi_quotes)启用后，您不能使用双引号来引用文字字符串，因为它们被解释为标识符。

-   [](<>) [`ERROR_FOR_DIVISION_BY_ZERO`](sql-mode.html#sqlmode_error_for_division_by_zero)

    [](<>)[](<>)

    这[`ERROR_FOR_DIVISION_BY_ZERO`](sql-mode.html#sqlmode_error_for_division_by_zero)模式影响除以零的处理，其中包括[`模组（*`ñ`*,0)`](mathematical-functions.html#function_mod).对于数据更改操作（[`插入`](insert.html),[`更新`](update.html))，其效果还取决于是否启用了严格的 SQL 模式。

    -   如果未启用此模式，则插入除以零`空值`并且不产生警告。

    -   如果启用此模式，则除以零插入`空值`并产生警告。

    -   如果启用此模式和严格模式，除以零会产生错误，除非`忽视`也给出了。为了`插入忽略`和`更新忽略`, 除以零插入`空值`并产生警告。

        为了[`选择`](select.html), 除以零返回`空值`.启用[`ERROR_FOR_DIVISION_BY_ZERO`](sql-mode.html#sqlmode_error_for_division_by_zero)无论是否启用严格模式，也会导致产生警告。

    [`ERROR_FOR_DIVISION_BY_ZERO`](sql-mode.html#sqlmode_error_for_division_by_zero)已弃用。[`ERROR_FOR_DIVISION_BY_ZERO`](sql-mode.html#sqlmode_error_for_division_by_zero)不是严格模式的一部分，但应与严格模式结合使用，默认启用。如果出现警告[`ERROR_FOR_DIVISION_BY_ZERO`](sql-mode.html#sqlmode_error_for_division_by_zero)在不启用严格模式的情况下启用，反之亦然。

    因为[`ERROR_FOR_DIVISION_BY_ZERO`](sql-mode.html#sqlmode_error_for_division_by_zero)已弃用，您应该期望它在未来的 MySQL 版本中作为单独的模式名称被删除，并且它的影响包含在严格 SQL 模式的影响中。

-   [](<>) [`HIGH_NOT_PRECEDENCE`](sql-mode.html#sqlmode_high_not_precedence)

    [](<>)[](<>)

    的优先级[`不是`](logical-operators.html#operator_not)运算符是这样的表达式，例如`不在 b 和 c 之间`被解析为`不是（b 和 c 之间的 a）`.在一些旧版本的 MySQL 中，表达式被解析为`（非 a）在 b 和 c 之间`.旧的高优先级行为可以通过启用[`HIGH_NOT_PRECEDENCE`](sql-mode.html#sqlmode_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
    ```

-   [](<>) [`忽略空格`](sql-mode.html#sqlmode_ignore_space)

    [](<>)[](<>)

    允许函数名和函数名之间有空格`(`特点。这会导致内置函数名称被视为保留字。因此，必须引用与函数名称相同的标识符，如中所述[第 9.2 节，“架构对象名称”](identifiers.html).例如，因为有一个[`数数（）`](aggregate-functions.html#function_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-mode.html#sqlmode_ignore_space)SQL 模式适用于内置函数，不适用于可加载函数或存储函数。始终允许在可加载函数或存储函数名称之后有空格，无论是否[`忽略空格`](sql-mode.html#sqlmode_ignore_space)已启用。

    进一步讨论[`忽略空格`](sql-mode.html#sqlmode_ignore_space)， 看[第 9.2.5 节，“函数名称解析和解析”](function-resolution.html).

-   [](<>) [`NO_AUTO_VALUE_ON_ZERO`](sql-mode.html#sqlmode_no_auto_value_on_zero)

    [](<>)[](<>)

    [`NO_AUTO_VALUE_ON_ZERO`](sql-mode.html#sqlmode_no_auto_value_on_zero)影响处理`自动递增`列。通常，您可以通过插入`空值`要么`0`进去。[`NO_AUTO_VALUE_ON_ZERO`](sql-mode.html#sqlmode_no_auto_value_on_zero)抑制这种行为`0`所以只有`空值`生成下一个序列号。

    这种模式很有用，如果`0`已存储在表中`自动递增`柱子。（存储`0`顺便说一句，这不是推荐的做法。）例如，如果您使用[**mysql转储**](mysqldump.html)然后重新加载它，MySQL通常会在遇到`0`值，导致表的内容与转储的表不同。启用[`NO_AUTO_VALUE_ON_ZERO`](sql-mode.html#sqlmode_no_auto_value_on_zero)在重新加载转储文件之前解决了这个问题。为此原因，[**mysql转储**](mysqldump.html)自动在其输出中包含一个启用[`NO_AUTO_VALUE_ON_ZERO`](sql-mode.html#sqlmode_no_auto_value_on_zero).

-   [](<>) [`NO_BACKSLASH_ESCAPE`](sql-mode.html#sqlmode_no_backslash_escapes)

    [](<>)[](<>)

    启用此模式将禁用反斜杠字符 (`\`) 作为字符串和标识符中的转义字符。启用此模式后，反斜杠将变为与其他任何字符一样的普通字符，并且默认转义序列为[`喜欢`](string-comparison-functions.html#operator_like)表达式已更改，因此不使用转义字符。

-   [](<>) [`NO_DIR_IN_CREATE`](sql-mode.html#sqlmode_no_dir_in_create)

    [](<>)[](<>)

    创建表时，忽略所有`索引目录`和`数据目录`指令。此选项在副本服务器上很有用。

-   [](<>) [`NO_ENGINE_SUBSTITUTION`](sql-mode.html#sqlmode_no_engine_substitution)

    [](<>)[](<>)

    控制默认存储引擎的自动替换，例如[`创建表`](create-table.html)要么[`更改表`](alter-table.html)指定禁用或未编译的存储引擎。

    默认，[`NO_ENGINE_SUBSTITUTION`](sql-mode.html#sqlmode_no_engine_substitution)已启用。

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

    和[`NO_ENGINE_SUBSTITUTION`](sql-mode.html#sqlmode_no_engine_substitution)禁用，对于[`创建表`](create-table.html)使用默认引擎，如果所需引擎不可用，则会出现警告。为了[`更改表`](alter-table.html), 出现警告并且表格没有改变。

    和[`NO_ENGINE_SUBSTITUTION`](sql-mode.html#sqlmode_no_engine_substitution)启用，如果所需的引擎不可用，则会发生错误并且不会创建或更改表。

-   [](<>) [`NO_UNSIGNED_SUBTRACTION`](sql-mode.html#sqlmode_no_unsigned_subtraction)

    [](<>)[](<>)

    整数值之间的减法，其中一个是类型`未签名`, 默认情况下产生无符号结果。如果结果本来是否定的，则会导致错误：

    ```
    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-mode.html#sqlmode_no_unsigned_subtraction)启用 SQL 模式，结果是否定的：

    ```
    mysql> SET sql_mode = 'NO_UNSIGNED_SUBTRACTION';
    mysql> SELECT CAST(0 AS UNSIGNED) - 1;
    +-------------------------+
    | CAST(0 AS UNSIGNED) - 1 |
    +-------------------------+
    |                      -1 |
    +-------------------------+
    ```

    如果此类操作的结果用于更新`未签名`整数列，结果被剪裁为列类型的最大值，或者剪裁为 0，如果[`NO_UNSIGNED_SUBTRACTION`](sql-mode.html#sqlmode_no_unsigned_subtraction)已启用。启用严格 SQL 模式时，会发生错误，并且列保持不变。

    什么时候[`NO_UNSIGNED_SUBTRACTION`](sql-mode.html#sqlmode_no_unsigned_subtraction)启用，减法结果有符号，*即使任何操作数是无符号的*.例如比较列的类型`c2`在表中`t1`与列`c2`在表中`t2`：

    ```
    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 未签名`并非在所有情况下都 100% 可用。看[第 12.11 节，“转换函数和运算符”](cast-functions.html).

-   [](<>) [`NO_ZERO_DATE`](sql-mode.html#sqlmode_no_zero_date)

    [](<>)[](<>)

    这[`NO_ZERO_DATE`](sql-mode.html#sqlmode_no_zero_date)模式影响服务器是否允许`'0000-00-00'`作为有效日期。其效果还取决于是否启用了严格的 SQL 模式。

    -   如果未启用此模式，`'0000-00-00'`是允许的，并且插入不会产生警告。

    -   如果启用此模式，`'0000-00-00'`是允许的，并且插入会产生警告。

    -   如果启用了此模式和严格模式，`'0000-00-00'`是不允许的，插入会产生错误，除非`忽视`也给出了。对于`插入忽略`和`更新忽略`,`'0000-00-00'`是允许的，插入物会产生警告。

    [`没有约会`](sql-mode.html#sqlmode_no_zero_date)不推荐使用。[`没有约会`](sql-mode.html#sqlmode_no_zero_date)不是严格模式的一部分，但应与严格模式结合使用，并在默认情况下启用。如果[`没有约会`](sql-mode.html#sqlmode_no_zero_date)在不启用严格模式的情况下启用，反之亦然。

    因为[`没有约会`](sql-mode.html#sqlmode_no_zero_date)如果已弃用，您应该期望在将来的MySQL版本中将其作为单独的模式名称删除，并且其效果包含在strict SQL模式的效果中。

-   [](<>) [`没有零年的约会`](sql-mode.html#sqlmode_no_zero_in_date)

    [](<>)[](<>)

    这个[`没有零年的约会`](sql-mode.html#sqlmode_no_zero_in_date)模式会影响服务器是否允许年部分不为零但月或日部分为0的日期。（此模式会影响以下日期：`'2010-00-01'`或`'2010-01-00'`，但不是`'0000-00-00'`.控制服务器是否允许`'0000-00-00'`， 使用[`NO_ZERO_DATE`](sql-mode.html#sqlmode_no_zero_date)模式。）的效果[`NO_ZERO_IN_DATE`](sql-mode.html#sqlmode_no_zero_in_date)还取决于是否启用了严格的 SQL 模式。

    -   如果未启用此模式，则允许包含零部分的日期并且插入不会产生警告。

    -   如果启用此模式，零部分的日期将插入为`'0000-00-00'`并发出警告。

    -   如果启用此模式和严格模式，则不允许包含零部分的日期并且插入会产生错误，除非`忽视`也给出了。为了`插入忽略`和`更新忽略`, 零部分的日期插入为`'0000-00-00'`并发出警告。

    [`NO_ZERO_IN_DATE`](sql-mode.html#sqlmode_no_zero_in_date)已弃用。[`NO_ZERO_IN_DATE`](sql-mode.html#sqlmode_no_zero_in_date)不是严格模式的一部分，但应与严格模式结合使用，默认启用。如果出现警告[`NO_ZERO_IN_DATE`](sql-mode.html#sqlmode_no_zero_in_date)在不启用严格模式的情况下启用，反之亦然。

    因为[`NO_ZERO_IN_DATE`](sql-mode.html#sqlmode_no_zero_in_date)已弃用，您应该期望它在未来的 MySQL 版本中作为单独的模式名称被删除，并且它的影响包含在严格 SQL 模式的影响中。

-   [](<>) [`ONLY_FULL_GROUP_BY`](sql-mode.html#sqlmode_only_full_group_by)

    [](<>)[](<>)[](<>)

    拒绝选择列表的查询，`拥有`条件，或`订购方式`list 指的是未在`通过...分组`子句在功能上也不依赖于（唯一确定的）`通过...分组`列。

    标准 SQL 的 MySQL 扩展允许在`拥有`子句到选择列表中的别名表达式。这`拥有`子句可以引用别名，无论是否[`ONLY_FULL_GROUP_BY`](sql-mode.html#sqlmode_only_full_group_by)已启用。

    有关其他讨论和示例，请参阅[第 12.20.3 节，“MySQL 对 GROUP BY 的处理”](group-by-handling.html).

-   [](<>) [`PAD_CHAR_TO_FULL_LENGTH`](sql-mode.html#sqlmode_pad_char_to_full_length)

    [](<>)[](<>)

    默认情况下，尾随空格从[`字符`](char.html)检索时的列值。如果[`PAD_CHAR_TO_FULL_LENGTH`](sql-mode.html#sqlmode_pad_char_to_full_length)启用，修剪不会发生并检索[`字符`](char.html)值被填充到它们的全长。此模式不适用于[`VARCHAR`](char.html)列，在检索时保留尾随空格。

    笔记

    从 MySQL 8.0.13 开始，[`PAD_CHAR_TO_FULL_LENGTH`](sql-mode.html#sqlmode_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`](sql-mode.html#sqlmode_pipes_as_concat)

    [](<>)[](<>)

    对待[`||`](logical-operators.html#operator_or)作为字符串连接运算符（与[`连接（）`](string-functions.html#function_concat)) 而不是作为同义词[`要么`](logical-operators.html#operator_or).

-   [](<>) [`REAL_AS_FLOAT`](sql-mode.html#sqlmode_real_as_float)

    [](<>)[](<>)

    对待[`真实的`](floating-point-types.html)作为同义词[`漂浮`](floating-point-types.html).默认情况下，MySQL 将[`真实的`](floating-point-types.html)作为同义词[`双倍的`](floating-point-types.html).

-   [](<>) [`STRICT_ALL_TABLES`](sql-mode.html#sqlmode_strict_all_tables)

    [](<>)[](<>)

    为所有存储引擎启用严格的 SQL 模式。无效的数据值被拒绝。有关详细信息，请参阅[严格的 SQL 模式](sql-mode.html#sql-mode-strict).

-   [](<>) [`STRICT_TRANS_TABLES`](sql-mode.html#sqlmode_strict_trans_tables)

    [](<>)[](<>)

    为事务存储引擎启用严格的 SQL 模式，并在可能的情况下为非事务存储引擎启用。有关详细信息，请参阅[严格的 SQL 模式](sql-mode.html#sql-mode-strict).

-   [](<>) [`TIME_TRUNCATE_FRACTIONAL`](sql-mode.html#sqlmode_time_truncate_fractional)

    [](<>)[](<>)

    控制插入时是否发生舍入或截断[`时间`](time.html),[`日期`](datetime.html)， 要么[`时间戳`](datetime.html)将带有小数秒部分的值放入具有相同类型但小数位数较少的列中。默认行为是使用舍入。如果启用此模式，则会发生截断。以下语句序列说明了差异：

    ```
    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 |
    +------+------------+
    ```

    也可以看看[第 11.2.6 节，“时间值中的小数秒”](fractional-seconds.html).

#### 组合 SQL 模式

提供以下特殊模式作为上述列表中模式值组合的简写。

-   [](<>) [`ANSI`](sql-mode.html#sqlmode_ansi)

    [](<>)[](<>)

    相当于[`REAL_AS_FLOAT`](sql-mode.html#sqlmode_real_as_float),[`PIPES_AS_CONCAT`](sql-mode.html#sqlmode_pipes_as_concat),[`ANSI_QUOTES`](sql-mode.html#sqlmode_ansi_quotes),[`忽略空格`](sql-mode.html#sqlmode_ignore_space)， 和[`ONLY_FULL_GROUP_BY`](sql-mode.html#sqlmode_only_full_group_by).

    [`ANSI`](sql-mode.html#sqlmode_ansi)模式还会导致服务器返回一个错误的查询，其中一个集合函数*`小号`*带有外部参考`*`小号`*(*`外部参考`*)`无法在已解析外部引用的外部查询中聚合。这是这样一个查询：

    ```
    SELECT * FROM t1 WHERE t1.a IN (SELECT MAX(t1.b) FROM t2 WHERE ...);
    ```

    这里，[`最大值(t1.b)`](aggregate-functions.html#function_max)无法在外部查询中聚合，因为它出现在`在哪里`该查询的子句。在这种情况下，标准 SQL 需要一个错误。如果[`ANSI`](sql-mode.html#sqlmode_ansi)模式未启用，服务器将`*`小号`*(*`外部参考`*)`在这样的查询中，它会以同样的方式解释`*`小号`*(*`常量`*)`.

    看[第 1.7 节，“MySQL 标准合规性”](compatibility.html).

-   [](<>) [`传统的`](sql-mode.html#sqlmode_traditional)

    [](<>)[](<>)

    [`传统的`](sql-mode.html#sqlmode_traditional)相当于[`STRICT_TRANS_TABLES`](sql-mode.html#sqlmode_strict_trans_tables),[`STRICT_ALL_TABLES`](sql-mode.html#sqlmode_strict_all_tables),[`NO_ZERO_IN_DATE`](sql-mode.html#sqlmode_no_zero_in_date),[`NO_ZERO_DATE`](sql-mode.html#sqlmode_no_zero_date),[`ERROR_FOR_DIVISION_BY_ZERO`](sql-mode.html#sqlmode_error_for_division_by_zero)， 和[`NO_ENGINE_SUBSTITUTION`](sql-mode.html#sqlmode_no_engine_substitution).

#### 严格的 SQL 模式

严格模式控制 MySQL 如何处理数据更改语句中的无效或缺失值，例如[`插入`](insert.html)要么[`更新`](update.html).一个值可能由于多种原因而无效。例如，它可能具有错误的列数据类型，或者可能超出范围。当要插入的新行不包含非`空值`没有明确的列`默认`条款中的定义。（为一个`空值`柱子，`空值`如果缺少值，则插入。）严格模式也会影响 DDL 语句，例如[`创建表`](create-table.html).

如果严格模式没有生效，MySQL 会为无效或缺失值插入调整值并产生警告（参见[第 13.7.7.42 节，“显示警告声明”](show-warnings.html)）。在严格模式下，您可以使用[`插入忽略`](insert.html)要么[`更新忽略`](update.html).

对于诸如[`选择`](select.html)不更改数据，无效值会在严格模式下生成警告，而不是错误。

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

严格模式不影响是否检查外键约束。[`foreign_key_checks`](server-system-variables.html#sysvar_foreign_key_checks)可以用于那个。（看[第 5.1.8 节，“服务器系统变量”](server-system-variables.html).)

严格 SQL 模式有效，如果[`STRICT_ALL_TABLES`](sql-mode.html#sqlmode_strict_all_tables)要么[`STRICT_TRANS_TABLES`](sql-mode.html#sqlmode_strict_trans_tables)已启用，尽管这些模式的效果有所不同：

-   对于事务表，当数据更改语句中的值无效或缺失时，会发生错误[`STRICT_ALL_TABLES`](sql-mode.html#sqlmode_strict_all_tables)要么[`STRICT_TRANS_TABLES`](sql-mode.html#sqlmode_strict_trans_tables)已启用。该语句被中止并回滚。

-   对于非事务性表，如果错误值出现在要插入或更新的第一行中，则任何一种模式的行为都是相同的：语句被中止，表保持不变。如果语句插入或修改多行，并且第二行或之后的行出现错误值，则结果取决于启用了哪种严格模式：

    -   为了[`STRICT_ALL_TABLES`](sql-mode.html#sqlmode_strict_all_tables), MySQL 返回错误并忽略其余行。但是，由于较早的行已被插入或更新，结果是部分更新。为避免这种情况，请使用单行语句，该语句可以在不更改表的情况下中止。

    -   为了[`STRICT_TRANS_TABLES`](sql-mode.html#sqlmode_strict_trans_tables), MySQL 将无效值转换为最接近列的有效值并插入调整后的值。如果缺少值，MySQL 会插入列数据类型的隐式默认值。在任何一种情况下，MySQL 都会生成警告而不是错误并继续处理该语句。隐式默认值在[第 11.6 节，“数据类型默认值”](data-type-defaults.html).

    严格模式会影响除以零、零日期和日期中的零的处理，如下所示：

-   严格模式会影响除以零的处理，其中包括[`模组（*`ñ`*,0)`](mathematical-functions.html#function_mod)：

    对于数据更改操作（[`插入`](insert.html),[`更新`](update.html)):

    -   如果未启用严格模式，则插入除以零`空值`并且不产生警告。

    -   如果启用严格模式，除以零会产生错误，除非`忽视`也给出了。为了`插入忽略`和`更新忽略`, 除以零插入`空值`并产生警告。

        为了[`选择`](select.html), 除以零返回`空值`.启用严格模式也会导致产生警告。

-   严格模式影响服务器是否允许`'0000-00-00'`作为有效日期：

    -   如果未启用严格模式，`'0000-00-00'`是允许的，并且插入不会产生警告。

    -   如果启用严格模式，`'0000-00-00'`不允许并且插入会产生错误，除非`忽视`也给出了。为了`插入忽略`和`更新忽略`,`'0000-00-00'`是允许的，并且插入会产生警告。

-   严格模式会影响服务器是否允许年份部分为非零但月或日部分为 0 的日期（例如`'2010-00-01'`要么`'2010-01-00'`):

    -   如果未启用严格模式，则允许包含零部分的日期并且插入不会产生警告。

    -   如果启用严格模式，则不允许包含零部分的日期并且插入会产生错误，除非`忽视`也给出了。为了`插入忽略`和`更新忽略`, 零部分的日期插入为`'0000-00-00'`（这被认为是有效的`忽视`) 并产生警告。

    有关严格模式的更多信息`忽视`， 看[IGNORE 关键字与严格 SQL 模式的比较](sql-mode.html#ignore-strict-comparison).

    严格模式会影响除以零、零日期和日期中的零以及与[`ERROR_FOR_DIVISION_BY_ZERO`](sql-mode.html#sqlmode_error_for_division_by_zero),[`NO_ZERO_DATE`](sql-mode.html#sqlmode_no_zero_date)， 和[`NO_ZERO_IN_DATE`](sql-mode.html#sqlmode_no_zero_in_date)模式。

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

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

下表显示了默认情况下生成错误与警告时语句行为的摘要比较。默认情况下会产生错误的示例是插入`空值`成一个`非空`柱子。默认情况下产生警告的一个示例是将错误数据类型的值插入到列中（例如插入字符串`'abc'`成一个整数列）。

| 操作模式 | 当 Statement Default 为 Error 时 | 当语句默认为警告时 |
| ---- | ----------------------------- | --------- |
| 没有`忽视`或严格的 SQL 模式 | 错误 | 警告 |
| 和`忽视` | 警告 | 警告（与没有相同`忽视`或严格的 SQL 模式） |
| 使用严格的 SQL 模式 | 错误（同无`忽视`或严格的 SQL 模式） | 错误 |
| 和`忽视`和严格的SQL模式 | 警告 | 警告 |

从表中得出的一个结论是，当`忽视`关键字和严格的 SQL 模式都有效，`忽视`优先。这意味着，虽然`忽视`和严格的SQL模式可以认为对错误处理有相反的作用，它们一起使用时不会取消。

-   [IGNORE 对语句执行的影响](sql-mode.html#ignore-effect-on-execution)

-   [严格 SQL 模式对语句执行的影响](sql-mode.html#strict-sql-mode-effect-on-execution)

##### IGNORE 对语句执行的影响

MySQL 中的几个语句支持可选的`忽视`关键词。此关键字导致服务器降级某些类型的错误并生成警告。对于多行语句，将错误降级为警告可能会处理一行。否则，`忽视`导致语句跳到下一行而不是中止。（对于不可忽略的错误，无论`忽视`关键词。）

示例：如果表`吨`有一个主键列`一世`包含唯一值，尝试插入相同的值`一世`进入多行通常会产生重复键错误：

```
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'
```

和`忽视`，仍然没有插入包含重复键的行，但是会出现警告而不是错误：

```
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`有个`非空`柱子`id`, 试图插入`空值`在严格的 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 模式不严格，`忽视`导致`空值`插入为隐式默认列（在本例中为 0），这样可以在不跳过它的情况下处理该行：

```
mysql> INSERT INTO t2 (id) VALUES(1),(NULL),(3);
mysql> SELECT * FROM t2;
+----+
| id |
+----+
|  1 |
|  0 |
|  3 |
+----+
```

这些声明支持`忽视`关键词：

-   [`创建表...选择`](create-table.html)：`忽视`不适用于[`创建表`](create-table.html)要么[`选择`](select.html)语句的一部分，但要插入到由生成的行的表中[`选择`](select.html).在唯一键值上重复现有行的行将被丢弃。

-   [`删除`](delete.html)：`忽视`导致 MySQL 在删除行的过程中忽略错误。

-   [`插入`](insert.html)： 和`忽视`，与唯一键值上的现有行重复的行将被丢弃。设置为会导致数据转换错误的值的行改为设置为最接近的有效值。

    [](<>)对于未找到与给定值匹配的分区的分区表，`忽视`导致插入操作对包含不匹配值的行静默失败。

-   [`加载数据`](load-data.html),[`加载 XML`](load-xml.html)： 和`忽视`，与唯一键值上的现有行重复的行将被丢弃。

-   [`更新`](update.html)： 和`忽视`，不会更新在唯一键值上发生重复键冲突的行。更新为会导致数据转换错误的值的行将更新为最接近的有效值。

    这`忽视`关键字适用于以下可忽略的错误：


```
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`](server-system-variables.html#sysvar_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`](server-system-variables.html#sysvar_sql_mode)系统变量，见[第 5.1.11 节，“服务器 SQL 模式”](sql-mode.html).

严格的 SQL 模式适用于以下语句，其中某些值可能超出范围或在表中插入或删除无效行：

-   [`更改表`](alter-table.html)

-   [`创建表`](create-table.html)

-   [`创建表...选择`](create-table.html)

-   [`删除`](delete.html)（单表和多表）

-   [`插入`](insert.html)

-   [`加载数据`](load-data.html)

-   [`加载 XML`](load-xml.html)

-   [`选择睡眠（）`](select.html)

-   [`更新`](update.html)（单表和多表）

    在存储程序中，如果程序是在严格模式生效时定义的，那么刚刚列出的类型的各个语句将在严格 SQL 模式下执行。

    严格 SQL 模式适用于以下错误，这些错误表示输入值无效或缺失的一类错误。如果某个值的列数据类型错误或可能超出范围，则该值无效。如果要插入的新行不包含`非空`没有明确的列`默认`条款中的定义。


```
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 模式。
