1.7.3.3对无效数据的约束

默认情况下,MySQL是原谅无效或不正确的数据值,并强制他们到数据输入的有效值。但是,您可以启用严格的SQL模式来选择更差的传统处理方法,以使服务器拒绝它们并中止其发生的语句。请参见第5.1.8节“服务器SQL模式”

本节介绍MySQL的默认(forgiving)行为,以及严格的SQL模式及其不同之处。

如果你不使用严格模式,那么当你插入一个“不正确”的值成一列,如NULLNOT NULL列,或将过大的数值插入数值列,MySQL会将这些列设置为“最可能值”而不是产生错误:以下规则更详细地描述了如何工作:

  • 如果您尝试将一个超出范围的值存储到数字列中,MySQL Server会将零,最小可能值或最大可能值(取最接近无效值)取代。

  • 对于字符串,MySQL存储空字符串或可存储在列中的字符串数量。

  • 如果您尝试将一个不以数字开头的字符串存储到数字列中,则MySQL Server将存储0。

  • 根据第1.7.3.4节“ENUM和SET约束”所述处理ENUMSET列的无效值。

  • MySQL允许您存储某些不正确的日期值DATEDATETIME列(例如'2000-02-31''2000-02-00')。在这种情况下,当应用程序尚未启用严格的SQL模式时,应用程序在存储日期之前验证它们。如果MySQL可以存储日期值并检索完全相同的值,MySQL将其存储为给定的。如果日期是完全错误的(服务器存储的能力之外),则特殊的“零”日期值'0000-00-00'将被存储在列中。

  • 如果您尝试存储NULL到不采取NULL值的列中,则单行INSERT语句将发生错误。对于多行INSERT语句或forINSERT INTO ... SELECT语句,MySQL Server存储列数据类型的隐式默认值。一般来说,这是0数字类型,字符串类型的空字符串('')和日期和时间类型的“零”值。第11.6节“数据类型默认值”中讨论了隐式默认值。

  • 如果一条INSERT语句不指定列的值,则如果列定义包含explicitDEFAULT子句,MySQL将插入其默认值。如果定义没有这样的DEFAULT子句,MySQL会为列数据类型插入隐式的默认值。

在非限制模式下使用上述规则的原因是,在语句开始执行之前,我们无法检查这些条件。如果在更新几行后遇到问题,我们不能回滚,因为存储引擎可能不支持回滚。终止声明的选择不是那么好;在这种情况下,更新将“半完成”,这可能是最糟糕的情况。在这种情况下,最好是“尽可能的”,然后继续,就好像没有发生任何事情。

您可以使用STRICT_TRANS_TABLESSTRICT_ALL_TABLESSQL模式选择更严格的输入值处理:

SET sql_mode ='STRICT_TRANS_TABLES';

SET sql_mode ='STRICT_ALL_TABLES';

STRICT_TRANS_TABLES为事务性存储引擎提供严格的模式,在某种程度上也支持非事务性引擎。它的工作原理如下:

  • 对于事务性存储引擎,语句中任何地方发生的不良数据值会导致语句中止并回滚。

  • 对于非事务性存储引擎,如果错误发生在要插入或更新的第一行中,则该语句将中止。(当第一行出现错误时,可以中止该语句,使表不变,就像事务表一样。)第一行后的行错误不会中止该语句,因为该表已被第一排。相反,错误的数据值被调整,并产生警告而不是错误。换句话说,使用STRICT_TRANS_TABLES错误的值会导致MySQL回滚到目前为止完成的所有更新,如果可以在不更改表的情况下完成。但是一旦表格发生变化,

对于更严格的检查,启用STRICT_ALL_TABLES。这是一样的STRICT_TRANS_TABLES,只是对非事务性存储引擎,错误甚至中止语句的第一行以下行不良数据。这意味着如果非交易表的多行插入或更新中出现错误,则会部分更新。较早的行被插入或更新,但从错误点开始的行不是。为了避免非事务性表的使用,请使用单行语句,否则可以使用STRICT_TRANS_TABLES转换警告而不是错误。为了避免问题,请不要使用MySQL来检查列的内容。

无论使用哪种严格的模式选项,您可以通过使用引起的警告被视为错误INSERT IGNORE或者UPDATE IGNORE,而不是INSERTUPDATEIGNORE

results matching ""

    No results matching ""