【问题标题】:How can I block '0000-00-00 00:00:00' date values from getting into my MySQL table?如何阻止“0000-00-00 00:00:00”日期值进入我的 MySQL 表?
【发布时间】:2014-04-29 21:25:10
【问题描述】:

我在 OS X 10.9.1 上使用 MySQL 5.5.37。我有一个NOT NULL 类型的DATETIME 列。在不使用触发器的情况下,如何阻止“0000-00-00 00:00:00”值进入我的列?我将接受一个 CURRENT_TIMESTAMP 值来代替所有的零。

我试过了:

SET sql_mode = 'NO_ZERO_DATE';

运行上述操作后,我仍然能够在表中插入零日期。

【问题讨论】:

标签: mysql sql date datetime


【解决方案1】:

不使用触发器(您声明的条件),您就不能。但是,根据the MySQL documentation

NO_ZERO_DATE 模式影响服务器是否允许“0000-00-00”作为有效日期。 其效果还取决于是否启用了严格的SQL 模式。

  • 如果此模式启用,则允许“0000-00-00”并且插入不会产生警告。

  • 如果启用此模式,则允许“0000-00-00”并且插入会产生警告。

  • 如果启用此模式和严格模式,则不允许使用 '0000-00-00' 并且插入会产生错误,除非同时给出 IGNORE。对于INSERT IGNOREUPDATE IGNORE,允许使用“0000-00-00”,插入会产生警告。

所以你应该确保严格的 SQL 模式也被启用。但即便如此,作为a commenter has pointed out,这也不一定有效。 MySQL 也忽略了检查约束,因此这也不起作用。如果你不想use a trigger,那你就卡住了。

【讨论】:

  • 这只是解释了为什么NO_ZERO_DATE 不起作用。它没有回答要做什么的问题。您编辑了答案以加粗有关严格 SQL 模式的部分,但您引用的文本显示该错误仍然即使在严格模式下也可能成为警告(导致插入虚假日期)。
  • 我以为很明显,我把OP需要做的事情加粗,并在最后加了一句再说一遍。
  • Here's an SQL Fiddle 显示它实际上并没有阻止'0000-00-00'被插入。
  • @hvd 很有趣,如果 OP 坚持使用 DATETIME 而不是 TIMESTAMP,并且不会使用触发器,那么不确定会有什么帮助。
  • 是的,我认为你是对的,触发器是可靠地防止它的唯一方法。
【解决方案2】:

正确的 SQL 答案是在列上添加 check 约束:

create table foo
(
  ...
  bar datetime not null check ( bar != '0000-00-00 00:00:00' ) ,
  ...
)

然而,根据create table 文档中的 sotto vocce 评论,mySql 虽然非常乐意解析并名义上“接受”check 约束定义,但它会默默地忽略它们:

CHECK 子句被解析,但被所有存储引擎忽略。

为此,您可能希望添加一个before insert 触发器来强制执行约束。您可能还应该强制日期实际上是有效日期,因为显然 mySql 甚至没有在 datedatetime 列中强制执行最小约束:

MySQL 允许您将某些不正确的日期值存储到 DATEDATETIME 列(例如“2000-02-31”或“2000-02-00”)。这个想法是,这不是工作 SQL 服务器的验证日期。如果 MySQL 可以存储日期值并检索 完全相同的值,MySQL 将其存储为给定。 如果日期完全错误(超出服务器的存储能力),特殊的 “零”日期值“0000-00-00”存储在列中。

有关如何创建此类触发器的详细信息,请参阅此问题:Mysql CHECK Constraint

【讨论】:

    【解决方案3】:

    您的数据库不应负责验证您的脚本尝试插入的数据。

    它应该检查给定的数据是否与列的边界匹配(不为空、类型和长度),但并不真正关心实际的内容

    如果您将列设置为NOT NULL,MySQL 仍将接受空字符串、00000-00-00 作为字符串/int/日期的“有效”值。

    数据库应该存储数据 - 而不是验证它。如果您想拒绝无效数据,这是您选择的编程语言应该执行的任务。否则(夸大其词)您可以将 UI 与数据库连接并省略任何“后端”逻辑。

    【讨论】:

    • @GordonLinoff 甚至可以随意投反对票 - 为什么数据库要接管“逻辑”决策?如果有人不想让日期“XXXX-12-24”因为那是圣诞节怎么办?数据库是否应该为此提供一个选项?
    • 。 .一年多前,我停止投票,但这确实扩大了我的信念。数据库实际上比应用程序更适合验证数据。但是,这与所提出的问题无关。
    • @GordonLinoff 好吧,我不同意这一点。如果数据与列的边界匹配,则数据库应存储它。关于实际内容的决定应该由使用数据库的代码决定——比如“不允许过去的日期”、“不允许这个人超过 150 岁的生日”等等。但是,也许您有一个示例,其中数据库可能是“验证数据的更好地方”?
    • 。 .我处理过的每一个合理的应用程序。数据库是数据存储。这就是为什么数据库支持check 约束和其他验证数据的方法。数据库应该只存储满足应用程序要求的数据。检查越接近数据,就越有可能真正得到一致实施。
    • @GordonLinoff 我绝对同意,数据库应该只包含有效数据。但在 FORMAT 和 TYPE 方面有效 - 而不是在内容方面。如果想将“false”存储在布尔列中,那应该可以!应该没有约束只允许“真实”......好吧:不同的意见。我会记住你的方法,也许会找到一个用例——即使“现在”很难想象。
    猜你喜欢
    • 2013-06-09
    • 2017-09-21
    • 2016-06-04
    • 1970-01-01
    • 2015-07-19
    • 2013-07-12
    • 1970-01-01
    • 2011-04-22
    • 1970-01-01
    相关资源
    最近更新 更多