【MySQL精通之路】MySQL8.0-SQL模式

目录

1.什么是SQL模式

2.设置SQL模式

[2.1 类型](#2.1 类型)

[2.2 方式](#2.2 方式)

3.重要的SQL模式

4.所有SQL模式

[4.1 ALLOW_INVALID_DATES](#4.1 ALLOW_INVALID_DATES)

[4.2 ANSI_QUOTES](#4.2 ANSI_QUOTES)

[4.3 ERROR_FOR_DIVISION_BY_ZERO](#4.3 ERROR_FOR_DIVISION_BY_ZERO)

[4.4 HIGH_NOT_PRECEDENCE](#4.4 HIGH_NOT_PRECEDENCE)

[4.5 IGNORE_SPACE](#4.5 IGNORE_SPACE)

[4.6 NO_AUTO_VALUE_ON_ZERO](#4.6 NO_AUTO_VALUE_ON_ZERO)

[4.7 NO_BACKSLASH_ESCAPES](#4.7 NO_BACKSLASH_ESCAPES)

[4.8 NO_DIR_IN_CREATE](#4.8 NO_DIR_IN_CREATE)

[4.9 NO_ENGINE_SUBSTITUTION](#4.9 NO_ENGINE_SUBSTITUTION)

[4.10 NO_UNSIGNED_SUBTRACTION](#4.10 NO_UNSIGNED_SUBTRACTION)

[4.11 NO_ZERO_DATE](#4.11 NO_ZERO_DATE)

[4.12 ONLY_FULL_GROUP_BY](#4.12 ONLY_FULL_GROUP_BY)

[4.13 PAD_CHAR_TO_FULL_LENGTH](#4.13 PAD_CHAR_TO_FULL_LENGTH)

[4.14 PIPES_AS_CONCAT](#4.14 PIPES_AS_CONCAT)

[4.15 REAL_AS_FLOAT](#4.15 REAL_AS_FLOAT)

[4.16 STRICT_ALL_TABLES](#4.16 STRICT_ALL_TABLES)

[4.17 STRICT_TRANS_TABLES](#4.17 STRICT_TRANS_TABLES)

[4.18 TIME_TRUNCATE_FRACTIONAL](#4.18 TIME_TRUNCATE_FRACTIONAL)

5.混合SQL模式

6.严格SQL模式

[6.1 NULL](#6.1 NULL)

[6.2 DDL](#6.2 DDL)

[6.3 SELECT](#6.3 SELECT)

[6.4 密钥](#6.4 密钥)

[6.5 外检约束](#6.5 外检约束)

[6.6 事务](#6.6 事务)

[6.7 零和IGNORE](#6.7 零和IGNORE)

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

[7.1 IGNORE对语句执行的影响](#7.1 IGNORE对语句执行的影响)

[7.1.1 支持IGNORE关键字的语句](#7.1.1 支持IGNORE关键字的语句)

[7.1.1.1 CREATE TABLE ... SELECT:](#7.1.1.1 CREATE TABLE ... SELECT:)

[7.1.1.2 DELETE:](#7.1.1.2 DELETE:)

[7.1.1.3 INSERT:](#7.1.1.3 INSERT:)

[7.1.1.4 LOAD DATA,LOAD XML:](#7.1.1.4 LOAD DATA,LOAD XML:)

[7.1.1.5 UPDATE](#7.1.1.5 UPDATE)

[7.1.2 IGNORE关键字适用于以下可忽略的错误](#7.1.2 IGNORE关键字适用于以下可忽略的错误)

[7.2 严格SQL模式对语句执行的影响](#7.2 严格SQL模式对语句执行的影响)

[7.2.1 零](#7.2.1 零)

[7.2.1 无效值](#7.2.1 无效值)

[7.2.2 语句适用性](#7.2.2 语句适用性)


1.什么是SQL模式

MySQL服务器可以在不同的SQL模式下运行,并且可以根据sql_mode系统变量的值将这些模式应用于不同的客户端。

DBA可以设置全局SQL模式匹配站点服务器 的操作要求,并且每个应用程序可以根据自己的要求设置其会话的SQL模式

模式会影响MySQL支持的SQL语法 及其执行的数据验证检查

这使得在不同的环境中使用MySQL 以及将MySQL 与其他数据库服务器一起使用更容易。

有关MySQL中服务器SQL模式的常见问题的答案

请参阅"MySQL 8.0常见问题解答:服务器SQL模式"。

使用InnoDB表时,还应考虑InnoDB_strict_mode系统变量 。它允许对InnoDB表进行额外的错误检查

2.设置SQL模式

2.1 类型

MySQL 8.0中的默认SQL模式包括以下模式:

ONLY_FULL_GROUP _BY

STRICT_TRANS_TABLES

NO_ZERO_in_DATE

NO_ZERO_DATE

ERROR_FOR_DIVISION_BY_ZERO

NO_ENGINE_SUBSTITION

2.2 方式

要在服务器启动时设置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_modesql_modesql_mode 系统变量

sql 复制代码
SET GLOBAL sql_mode = 'modes';
SET SESSION sql_mode = 'modes';

设置GLOBAL变量 需要SYSTEM_VARIABLES_ADMIN权限(或SUPER权限,不推荐不安全),并且会影响从那时起连接的所有客户端的操作 。设置SESSION变量仅影响当前客户端。

每个客户端都可以随时更改其会话sql_mode值

要确定当前全局会话sql_mode设置,请选择其值:

sql 复制代码
SELECT @@GLOBAL.sql_mode;
SELECT @@SESSION.sql_mode;

重要:
SQL模式用户定义的分区

在创建数据并将数据插入分区表后更改服务器SQL模式可能会导致此类表的行为发生重大变化,并可能导致数据丢失或损坏。

强烈建议您在创建了使用用户定义分区的表后,不要更改SQL模式。

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

有关更多信息,请参阅"分区的限制和限制"。

3.重要的SQL模式

最重要的sql_mode值可能如下:

ANSI

此模式会更改语法和行为,以更接近标准SQL。这是本节末尾列出的特殊组合模式之一。

理解成基本模式

STRICT_TRANS_TABLES

如果某个值不能按照给定的方式插入事务表,会中止该语句

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

理解成严格模式

TRADITIONAL

让MySQL表现得像一个"传统"的SQL数据库系统。此模式的简单描述是在列中插入不正确的值时"给出错误而不是警告"。这是本节末尾列出的特殊组合模式之一。

理解成传统模式


注意:
启用传统模式后,一旦出现错误,INSERT或UPDATE就会中止。 如果您使用的是非事务存储引擎,这可能不是您想要的,因为在发生错误之前所做的数据更改可能不会回滚,从而导致"部分完成"更新。

4.所有SQL模式

4.1 ALLOW_INVALID_DATES

翻译:允许无效日期

不对日期进行全面检查。仅检查月份是否在1到12之间,日期是否在1和31之间。

这对于在三个不同的字段中获取年、月和日,并在没有日期验证的情况下准确存储用户插入的内容的Web应用程序来说可能很有用。

此模式适用于DATE和DATETIME列。

它不适用于始终需要有效日期的TIMESTAMP列。

在禁用ALLOW_INVALID_DATES的情况下,服务器要求月份和日期的值是合法的,而不仅仅是分别在1到12和1到31的范围内。

禁用严格模式后,无效日期(如"2004-04-31")将转换为"0000-00-00",并生成警告

启用严格模式后,无效日期会产生错误。要允许这样的日期,请启用ALLOW_INVALID_DATES.

4.2 ANSI_QUOTES

把 " 视为标识符字符 (如`引号字符),而不是字符串字符

启用此模式后,您仍然可以使用`对标识符进行引号引用。

启用ANSI_QUOTES后,您不能使用双引号 对文字字符串进行引号包含,因为它们被解释为标识符字符。

4.3 ERROR_FOR_DIVISION_BY_ZERO

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模式的效果中

4.4 HIGH_NOT_PRECEDENCE

NOT运算符的优先级使得诸如 NOT a BETWEEN b AND c 之类的表达式被解析为NOT(a BETWENE b AND c)

在一些旧版本的MySQL中,表达式被解析为**(NOT a)BETWEEN b AND c** 。可以通过启用HIGH_NOT_PRECDENCE SQL模式来获得旧的更高优先级行为

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

4.5 IGNORE_SPACE

允许函数名 和**"("字符之间有空格。这会导致内置函数名** 被视为保留字 。因此,与函数名相同的标识符必须引用 ,如**"**架构对象名称"所述。

例如,因为有一个COUNT()函数,在以下语句中将COUNT用作表名会导致错误:

sql 复制代码
mysql> CREATE TABLE count (i INT);
ERROR 1064 (42000): You have an error in your SQL syntax

正确写法:

sql 复制代码
mysql> CREATE TABLE `count` (i INT);
Query OK, 0 rows affected (0.00 sec)

4.6 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的语句

4.7 NO_BACKSLASH_ESCAPES

启用此模式将禁止在字符串和标识符中使用反斜杠字符(\)作为转义符

启用此模式后,反斜杠将像其他字符一样成为普通字符,like表达式的默认转义序列也将更改,因

此不使用转义字符。

4.8 NO_DIR_IN_CREATE

创建表时,请忽略所有INDEX DIRECTORYDATA DIRECTORY(数据字典)指令。此选项在副本服务器上很有用。

数据字典:

【MySQL精通之路】MySQL8.0官方文档-数据字典-CSDN博客

4.9 NO_ENGINE_SUBSTITUTION

当CREATE TABLE或ALTER TABLE等语句指定了禁用或未匹配的存储引擎时,控制默认存储引擎的自动替换。

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

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

在禁用NO_ENGINE_SUBSTITUTION的情况下,对于CREATE TABLE,将使用默认引擎,如果

所需引擎不可用,则会发出警告。

对于ALTER TABLE,将出现警告并且不会更改表。

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

4.10 NO_UNSIGNED_SUBTRACTION

默认情况下,整数值之间的相减(其中一个为UNSIGNED类型)会产生无符号结果。如果结果本来是负的,则会产生一个错误:

sql 复制代码
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模式,则结果为负数:

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的类型进行比较:

sql 复制代码
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节"强制转换函数和运算符"。

4.11 NO_ZERO_DATE

NO_ZERO_IN_DATE模式影响服务器是否允许年部分为非零但月或日部分为0的日期

(此模式会影响日期,如"2010-00-01"或"2010-01-00",但不会影响"0000-00-00"。要控制服务器是否允许"0000-00-00-00",请使用NO_ZERO_DATE模式。)NO_ZERO_IN_DATE的效果还取决于是否启用了严格的SQL模式。

如果未启用此模式,则允许零部分日期,并且插入不会产生任何警告。
如果启用此模式,则零部分日期插入为"0000-00-00",并产生警告。
如果启用此模式和严格模式,则不允许包含零部分的日期,并且插入会产生错误,除非也给出IGNORE。对于INSERT IGNORE和UPDATE IGNORE,零部分的日期插入为"0000-00-00"并产生警告。

不赞成使用NO_ZERO_IN_DATENO_ZERO_IN_DATE不是严格模式的一部分,但应与严格模式一起使用,并在默认情况下启用。如果启用NO_ZERO_IN_DATE而不启用严格模式,则会出现警告,反之亦然。

由于NO_ZERO_IN_DATE已被弃用,您应该预期它会在未来的MySQL版本中作为一个单独的模式名称被删除,其效果包含在严格SQL模式的效果中。

4.12 ONLY_FULL_GROUP_BY

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

博主PS:这里很重要!!!

标准SQL的MySQL扩展允许在HAVING子句 中引用选择列表中的别名表达式。HAVING子句可以引用别名,而不管是否启用了ONLY_FULL_GROUP _BY。

有关其他讨论和示例,请参阅"GROUP BY的MySQL处理"。

4.13 PAD_CHAR_TO_FULL_LENGTH

默认情况下,检索时会从CHAR列值中修剪尾部空格。如果启用了PAD_CHAR_TO_FULL_LENGTH ,则不会进行修剪,并且检索到的CHAR值将填充到其全长此模式不适用于VARCHAR列,检索时会保留其尾部空格。

注意:
从MySQL 8.0.13开始,不推荐使用PAD_CHAR_TO_FULL_LENGTH。预计它会在MySQL的未来版本中被删除。

sql 复制代码
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)

4.14 PIPES_AS_CONCAT

将||视为字符串串联运算符(与CONCAT()相同),而不是OR的同义词。

4.15 REAL_AS_FLOAT

将REAL视为FLOAT的同义词。默认情况下,MySQL将REAL视为DOUBLE的同义词。

4.16 STRICT_ALL_TABLES

为所有存储引擎启用严格的SQL模式。无效的数据值被拒绝。

有关详细信息,请参阅严格SQL模式。

4.17 STRICT_TRANS_TABLES

为事务性存储引擎启用严格的SQL模式,并在可能的情况下为非事务性存储发动机启用严格的SQL模式。

有关详细信息,请参阅严格SQL模式。

4.18 TIME_TRUNCATE_FRACTIONAL

控制在将具有小数秒部分的TIME、DATE或TIMESTAMP值插入到具有相同类型小数位数较少的列 中时,是进行舍入还是截断默认行为是使用舍入 。如果启用此模式,则会发生截断。以下陈述顺序说明了差异:

sql 复制代码
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);

生成的表内容如下所示,其中第一个值经过四舍五入,第二个值经过截断:

sql 复制代码
mysql> SELECT id, tval FROM t ORDER BY id;
+------+------------+
| id   | tval       |
+------+------------+
|    1 | 00:00:01.6 |
|    2 | 00:00:01.5 |
+------+------------+

另请参见"时间值中的分数秒"。

5.混合SQL模式

以下特殊模式是前面列表中模式值组合的简写。

ANSI等效于

REAL_AS_FLOAT

PIPES_AS_CONCAT

ANSI_QUOTES

IGNORE_SPACE

ONLY_FULL_GROUP _BY

ANSI模式还导致服务器为查询返回错误,其中具有外部引用S(outer_ref)的集合函数S无法在已解析外部引用的外部查询中聚合。这是这样一个查询:

sql 复制代码
SELECT * FROM t1 WHERE t1.a IN (SELECT MAX(t1.b) FROM t2 WHERE ...);

这里,**MAX(t1.b)**不能在外部查询中聚合,因为它出现在该查询的WHERE子句中。

在这种情况下,标准SQL需要一个错误。

如果未启用ANSI模式,则服务器在此类查询中处理S(outer_ref)的方式与解释S(const)的方式相同。

请参阅第1.6节"MySQL标准合规性"。

TRADITIONAL等效于

STRICT_TRANS_TABLES

STRICT_ALL_TABLES

NO_ZERO_IN_DATE

NO_ZERO_DATE

ERROR_FOR_DIVISION_BY_ZERO

NO_ENGINE_SUBSTITION

6.严格SQL模式

严格模式控制MySQL如何处理INSERT或UPDATE等数据更改语句中的无效或缺失值。

一个值可能由于多种原因而无效。

例如,它可能具有错误的列数据类型,或者可能超出范围。

6.1 NULL

如果要插入的新行不包含定义中没有显式DEFAULT子句的非NULL列的值,则缺少值。

(对于NULL列,如果缺少值,则插入NULL。)

6.2 DDL

严格模式也会影响DDL语句,如CREATE TABLE。

如果严格模式无效,MySQL会为无效或缺失的值插入调整后的值,并产生警告

(请参阅"显示警告语句")。

在严格模式下,可以通过使用INSERT IGNORE或UPDATE IGNORE来产生此行为。

6.3 SELECT

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

6.4 密钥

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

6.5 外检约束

严格模式不影响是否检查外键约束。foreign_key_checks可以用于此。

(请参阅"服务器系统变量"。)


6.6 事务

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

对于事务表,当启用STRICT_ALL_TABLESSTRICT_TRANS_TABLES时,数据更改语句中的值无效或丢失时会发生错误。语句被中止并回滚。
对于非事务表,如果在要插入或更新的第一行中出现错误值,则任何一种模式的行为都是相同的:

语句被中止,表保持不变。

如果语句插入或修改多行,而错误值出现在第二行或后面的行,则结果取决于启用了哪种严格模式:

对于STRICT_ALL_TABLES,MySQL返回一个错误并忽略其余行。但是,由于前面的行已经插入或更新,因此结果是部分更新。要避免这种情况,请使用单行语句,该语句可以在不更改表的情况下中止。

对于STRICT_TRANS_TABLES,MySQL将无效值转换为该列最接近的有效值,并插入调整后的值。如果缺少值,MySQL将插入列数据类型的隐式默认值。在任何一种情况下,MySQL都会生成一个警告而不是错误,并继续处理该语句。

"数据类型默认值"中描述了隐式默认值。

6.7 零和IGNORE

严格模式影响按零、零日期和日期中的零进行除法的处理,如下所示:

严格模式影响除以零的处理,包括MOD(N,0):

对于数据更改操作(INSERT、UPDATE):

如果未启用严格模式,则除以零将插入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",并且插入会产生警告。


严格模式影响服务器是否允许年部分为非零但月或日部分为0的日期(如"2010-00-01"或"2010-01-00"):

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

如果启用了严格模式,则不允许零部分的日期,并且插入会产生错误,除非也给出IGNORE。对于INSERT IGNORE和UPDATE IGNORE,包含零部分的日期被插入为"0000-00-00"(这被认为对IGNORE有效),并产生警告。

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

严格模式与ERROR_FOR_division_by_zero、NO_zero_DATE和NO_zero _in_DATE模式一起影响按零、零日期和日期中的零进行除法的处理。

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

本节比较IGNORE关键字(将错误降级为警告)和严格SQL模式(将警告升级为错误)对语句执行的影响。

它描述了它们影响哪些语句,以及它们应用于哪些错误。

下表显示了默认情况下生成错误与发出警告时语句行为的摘要比较。

默认情况下产生错误的一个示例是在NOT NULL列中插入NULL。

默认情况下生成警告的一个示例是将错误数据类型的值插入列(例如将字符串"abc"插入整数列)。

| 模式 | 默认Error | 默认Warning |
| 无IGNORE或严格 | Error | Warning |
| IGNORE | Warning | Warning (same as without IGNORE or strict SQL mode) |
| 严格 | Error (same as without IGNORE or strict SQL mode) | Error |

IGNORE +严格 Warning Warning

从表中可以得出的一个结论是,当IGNORE关键字和严格的SQL模式都有效时,IGNORE优先。这意味着,尽管IGNORE和严格的SQL模式可以被认为对错误处理有相反的影响,但它们在一起使用时不会取消。

7.1 IGNORE对语句执行的影响

MySQL中的一些语句支持可选的IGNORE关键字。

此关键字会导致服务器降级某些类型的错误并生成警告

对于多行语句,将错误降级为警告可以处理一行。

否则,IGNORE会导致语句跳到下一行,而不是中止。

(对于不可忽略的错误,无论IGNORE关键字如何,都会发生错误。)

示例:如果表t的主键列i包含唯一值,则尝试将相同的i值插入多行通常会产生重复的键错误:

sql 复制代码
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时,仍然不会插入包含重复密钥的行,但会出现警告而不是错误:

sql 复制代码
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为NOT NULL,则在严格的SQL模式下尝试插入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),这使行可以在不跳过它的情况下进行处理:

sql 复制代码
mysql> INSERT INTO t2 (id) VALUES(1),(NULL),(3);
mysql> SELECT * FROM t2;
+----+
| id |
+----+
|  1 |
|  0 |
|  3 |
+----+

7.1.1 支持IGNORE关键字的语句

7.1.1.1 CREATE TABLE ... SELECT:

IGNORE不适用于语句的CREATE TABLE或SELECT部分,而是插入到SELECT生成的行表中。在唯一键值上与现有行重复的行将被丢弃。

7.1.1.2 DELETE:

IGNORE导致MySQL在删除行的过程中忽略错误。

7.1.1.3 INSERT:

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

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

7.1.1.4 LOAD DATA,LOAD XML:

使用IGNORE,将丢弃在唯一键值上与现有行重复的行。

7.1.1.5 UPDATE

使用IGNORE,不会更新在唯一键值上发生重复键值冲突的行。更新为会导致数据转换错误的值的行将更新为最接近的有效值。

7.1.2 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

7.2 严格SQL模式对语句执行的影响

MySQL服务器可以在不同的SQL模式下运行,并且可以根据SQL_mode系统变量的值将这些模式应用于不同的客户端。在"严格"SQL模式下,服务器会将某些警告升级为错误。

7.2.1 零

例如,在非严格SQL模式下,将字符串"abc"插入整数列会导致值转换为0并发出警告:

sql 复制代码
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)

7.2.1 无效值

在严格的SQL模式中,无效值将被拒绝,并出现错误:

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系统变量可能设置的更多信息,请参阅"服务器sql模式"。

7.2.2 语句适用性

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

ALTER TABLE

CREATE TABLE

CREATE TABLE ... SELECT

DELETE (单表和多表)

INSERT

LOAD DATA

LOAD XML

SELECT SLEEP()

UPDATE (单表和多表)

在存储的程序中,如果程序是在严格模式有效时定义的,则刚才列出的类型的单个语句将以严格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模式适用于这些错误。

相关推荐
阿猿收手吧!3 分钟前
【Redis】Redis入门以及什么是分布式系统{Redis引入+分布式系统介绍}
数据库·redis·缓存
奈葵7 分钟前
Spring Boot/MVC
java·数据库·spring boot
leegong2311115 分钟前
Oracle、PostgreSQL该学哪一个?
数据库·postgresql·oracle
中东大鹅21 分钟前
MongoDB基本操作
数据库·分布式·mongodb·hbase
夜光小兔纸42 分钟前
Oracle 普通用户连接hang住处理方法
运维·数据库·oracle
兩尛2 小时前
订单状态定时处理、来单提醒和客户催单(day10)
java·前端·数据库
web2u2 小时前
MySQL 中如何进行 SQL 调优?
java·数据库·后端·sql·mysql·缓存
Elastic 中国社区官方博客3 小时前
使用 Elasticsearch 导航检索增强生成图表
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
小金的学习笔记3 小时前
RedisTemplate和Redisson的使用和区别
数据库·redis·缓存
新知图书4 小时前
MySQL用户授权、收回权限与查看权限
数据库·mysql·安全