目录
[2.1 类型](#2.1 类型)
[2.2 方式](#2.2 方式)
[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)
[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.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列的处理。
通常,您可以通过在列中插入NULL 或0来生成该列的下一个序列号。
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 DIRECTORY 和DATA 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_DATE 。NO_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_TABLES 或STRICT_TRANS_TABLES,则严格SQL模式有效,尽管这些模式的效果略有不同:
对于事务表,当启用STRICT_ALL_TABLES 或STRICT_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模式适用于这些错误。