【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模式适用于这些错误。

相关推荐
o(╥﹏╥)27 分钟前
linux(ubuntu )卡死怎么强制重启
linux·数据库·ubuntu·系统安全
阿里嘎多学长41 分钟前
docker怎么部署高斯数据库
运维·数据库·docker·容器
Yuan_o_44 分钟前
Linux 基本使用和程序部署
java·linux·运维·服务器·数据库·后端
Sunyanhui11 小时前
牛客网 SQL36查找后排序
数据库·sql·mysql
老王笔记1 小时前
MHA binlog server
数据库·mysql
lovelin+v175030409662 小时前
安全性升级:API接口在零信任架构下的安全防护策略
大数据·数据库·人工智能·爬虫·数据分析
DT辰白3 小时前
基于Redis的网关鉴权方案与性能优化
数据库·redis·缓存
2401_871213303 小时前
mysql高阶语句
数据库·mysql
Mitch3113 小时前
【漏洞复现】CVE-2021-45788 SQL Injection
sql·web安全·docker·prometheus·metersphere