我在OS X 10.9.1上使用MySQL 5.5.37。我有一个类型为DATETIME
的NOT NULL
列。在不使用触发器的情况下,如何阻止值"0000-00-00 00:00:00"进入我的列?我将接受一个CURRENT_TIMESTAMP值来代替所有的零。
我试过了:
SET sql_mode = 'NO_ZERO_DATE';
在完成上述操作后,我仍然可以在表中插入零日期。
如果不使用触发器(您声明的条件(,您就不能。然而,根据MySQL文档,
NO_ZERO_DATE
模式影响服务器是否允许"0000-00-00"作为有效日期其效果还取决于是否启用了严格的SQL
模式
-
如果此模式未启用,则允许"0000-00-00",并且插入不会产生警告。
-
如果启用了此模式,则允许"0000-00-00",并且插入会产生警告。
-
如果启用此模式和严格模式,则不允许使用"0000-00-00",并且插入会产生错误,除非也给出
IGNORE
。对于INSERT IGNORE
和UPDATE IGNORE
,允许使用"0000-00-00",插入会产生警告。
因此,您应该确保还启用了严格的SQL模式。但即便如此,正如一位评论者所指出的,这也不一定奏效。MySQL也忽略了检查约束,所以这也不起作用。如果你不想使用扳机,你就会被卡住。
SQL的正确答案是在列上添加check
约束:
create table foo
(
...
bar datetime not null check ( bar != '0000-00-00 00:00:00' ) ,
...
)
然而,mySql非常乐意解析并名义上"接受"check
约束定义,但根据create table
文档中的sotto-vocce注释,它会默默地忽略它们:
CHECK
子句经过解析,但被所有存储引擎忽略。
为此,您可能希望添加一个before insert
触发器来强制执行约束。您可能还应该强制该日期实际上是一个有效的日期,因为显然mySql甚至没有在date
和datetime
列中强制执行最小约束:
MySQL允许您将某些不正确的日期值存储到
DATE
和DATETIME
中列(如"2000-02-31"或"2000-02-00"(。想法是这不是工作以验证日期。如果MySQL可以存储日期值并检索完全相同的值,MySQL将其存储为给定值。如果日期完全错误(超出了服务器的存储能力("零"日期值"0000-00-00"存储在列中。
有关如何创建这样一个触发器的详细信息,请参阅此问题:Mysql CHECK Constraint
您的数据库不应负责验证脚本试图插入的数据。
它应该检查给定的数据是否与列的边界匹配(不是null、类型和长度(,但并不真正关心实际的内容。
如果将列设置为NOT NULL
,MySQL仍将接受空字符串0
或0000-00-00
作为string/int/date的"有效"值。
数据库应该存储数据,而不是验证它。如果你想拒绝无效数据,这是你选择的编程语言应该执行的任务。否则(言过其实(,您可以将UI与数据库连接起来,并省略任何"后端"逻辑。