为什么MySQL允许非空字段接受NULL值

4

我正在通过Laracast基础课程系列学习Laravel 5.1,在第7集中讲到了迁移,我像这样用迁移构建了一张表:

public function up()
{
    Schema::create('articles', function (Blueprint $table) {
        $table->increments('id');
        $table->string('title');
        $table->text('body');
        $table->timestamps();
        $table->timestamp('published_at');
    });
}

在第10集中提到,当我通过一个没有“published_at”时间戳字段的表单向数据库添加文章时,这应该不起作用,并且应该抛出一个“Not Null constraint failed”的异常。但是令人难以置信的是,文章被添加到了表中。 当我查看phpmyadmin的表结构中“published_at”列时,它没有选中“null”复选框,所以它不应该接受null?这是真的吗? 但是后来我注意到迁移将“published_at”列的默认值设置为“0000-00-00 00:00:00”。为什么?这会覆盖NULL条件吗? 然后我尝试将默认值设置为“none”,但仍然没有选中null。我再次尝试添加一个没有“published_at”字段的文章,但是仍然会在表中添加一行并将“published_at”值设置为“0000-00-00 00:00:00”。 有什么解释吗?
我正在使用带有“mysql v5.6.17”和“php v5.5.12”的wampserver。
2个回答

3

所有数据库类型都有默认值。当你创建一条记录并仅填写标题时,正文将被设置为空字符串,时间戳将被设置为“空”日期,即0000-00-00 00:00:00。如果你将这些字段设置为可为空,并为它们设置->default(null),则在这种情况下,它们将具有null值。

您也可以阅读关于MySql中类型的默认值的内容。


谢谢Marcin,我的表单中没有published_at的文本框,所以当我提交时,查询中会是null还是空字符串? - osyan
而且我没有将该字段设置为“可为空”。 - osyan
1
如果你的 published_at 不可为空,当你不填写它时,你会得到 0000-00-00 00:00:00,因为你没有设置任何其他默认值。你可以使用 ->default(DB::raw('CURRENT_TIMESTAMP')) 来设置它,这样当你不填写它时,你将默认获得当前日期和时间,而不是零。 - Marcin Nabiałek
我明白了你的意思,但是我仍然感到困惑,为什么在同样的情况下,在那个视频中会抛出异常。这可能是因为SQLite和MySQL之间的差异吗? - osyan
@osyan 我知道,但我不知道为什么会这样。我几乎一直使用MySql,但很遗憾我没有更多时间来测试这个问题。 - Marcin Nabiałek

1

SELECT @@SQL_MODE;

如果您没有看到其中一个严格SQL模式已启用,则MySQL正在使用其旧行为,并强制将无效值转换为有效值以允许插入该行。

如果未启用严格模式,则MySQL会插入已调整的值以替代无效或缺失的值,并生成警告。

随正式MySQL Server 5.6一起提供的默认配置文件启用了STRICT_TRANS_TABLES。WAMP可能没有遵循同样的惯例,可能是出于向后兼容性的原因...但可以更改配置。


1
谢谢,就像你说的那样,我有这个设置 @@SQL_MODE = NO_ENGINE_SUBSTITUTION,似乎类似的问题也发生在这里:https://dev59.com/SV8e5IYBdhLWcg3wJn2l#26035507。 - osyan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接