2012-12-10 46 views
20

当MySQL允许我将NULL插入到使用NOT NULL创建的字段中时,我非常惊讶。我做了一些研究,并发现如何启用严格模式。但是,我不太确定当启用STRICT_ALL_TABLES时MySQL做了什么验证。严格模式启用时,MySQL会做什么验证?

手册上说:

严格控制模式的MySQL如何处理是无效或丢失的输入值。 由于以下原因,值可能无效。(强调我的)例如,它可能有错误的数据类型的列,或者它可能超出范围。

我明白它认为丢失了什么以及如何处理它。我不清楚它认为无效。我做了一些测试,发现以下几点:

  • 字符串太长无效
  • 数字,超出范围是无效的
  • NULL■对于非NULL列无效
  • TRUEFALSE似乎总是有效(它们分别成为1和0)
  • 无效日期是无效的
  • 零日期是有效的(ADDIT有理模式启用后可改变这种行为)
  • 漂浮在整场是有效的(他们得到圆)在许多领域
  • 信件是无效

用MySQL做得比其他任何其他验证检查上面提到了什么?

该手册说'列的数据类型错误',但唯一的情况是我看到这个实际进入的地方是数字字段中的字母。还有其他数据类型错误的例子吗?

是否有一个列表正确地检查MySQL的性能?

编辑:为了记录,我的应用程序已经做了广泛的验证。我使用严格模式作为最后机会,即时检查。如果我忘记检查某些内容,我希望它快速失败而不是'默默地修改我的数据'。

+0

给我的感觉你想要DB为你做数据验证。如果是这样的话,这是一个不好的道路。 – siride

+3

@siride:DBMS ***是***在那里做验证(外键,主键,检查约束,类型验证)。 MySQL允许你存储'February,31st'这个事实在我看来是一个错误。或者换句话说:如果DBMS没有做任何验证,那么这是一条非常糟糕的路。 –

+4

我已经在应用程序中进行了验证。我*不*使用严格模式作为*替代品*以获得良好的编程,而是作为确保编程良好的一种方法。 – toxalot

回答

8

一个很好的资源是检查MySQL源代码,并阅读mysql-test/t/strict.test以查看在设置STRICT模式或TRADITIONAL模式(这是STRICT的超集)后测试的所有情况。

你做了出色的研究和试验,但也有一些更多的情况下,如:

  • 试图插入一个未定义的枚举值。
  • 尝试为NOT NULL列插入缺省值,但没有定义DEFAULT。
  • 尝试使用CAST()将字符串转换为整数,等
  • VARCHAR转化为MEDIUMTEXT或LONGTEXT如果你给的长度大于65536
  • 截断的表和列注释字符串的。
  • 将字符串转换为YEAR类型。
  • 定义具有重复条目的SET或ENUM列。

还有mysql-test/include/strict_autoinc.inc,因为当auto-inc值变得太大时它会测试溢出。

还有一些其他测试文件在特定测试中使用STRICT模式,但我没有检查它们。

+0

如何/在哪里可以找到源代码? – toxalot

+0

另一种情况是尝试将负数插入UNSIGNED列。 – toxalot

+0

http://dev.mysql.com/downloads/mysql/#downloads,选择“源代码”作为平台。 –

3

我grepped的MySQL 5.5.28(社区服务器版)的源代码来查找正在使用STRICT_ALL_TABLES的实例。

从我看到的看起来,您的列表看起来已经非常完整,但以下是我了解的有关使用STRICT_ALL_TABLES的其他一些信息。第一个是另一个验证,其余全部处理错误和警告。

  • 几何列不能有默认值。 (sql/field.cc:9394)
  • 如果一个表的注释长度超过2048个字符,MySQL会产生一个错误而不是截断该注释的警告。 (sql/unireg.cc:231)
  • 如果一个字段注释超过1024个字符,MySQL会产生一个错误,而不是截断该注释并带有警告。在插入或更新时,如果SET或ENUM中存在重复值,则MySQL产生错误而不是警告。 (sql/sql_table.cc:2503)
  • 有一堆操作会在用STRICT_ALL_TABLES警告时中止,而不是只处理警告。这些数量太多,我不能列出,并且abort_on_warning标志的设置与创建警告的代码相距太远,以便我轻松记录(甚至理解)所有这些警告。但是,如果有人想获得他们的手在源代码中脏,有几个地方开始将SQL/sql_update.cc:630SQL/sql_insert.cc:841