为了账号安全,请及时绑定邮箱和手机立即绑定

Laravel 在创建具有两个时间戳列的表时出错

Laravel 在创建具有两个时间戳列的表时出错

PHP
holdtom 2022-06-17 14:45:44
我在 Laravel 6.6 中创建了一个具有以下定义的表。public function up(){    Schema::create('quarters', function (Blueprint $table) {        $table->integer('quarter_id')->unsigned();        $table->integer('year')->unsigned();        $table->integer('quarter_num')->unsigned();        $table->timestamp('valid_from');        $table->timestamp('valid_to'); // <------ error on this line        $table->string('description')->nullable();        $table->timestamps();        $table->primary('quarter_id');    });} 当我运行迁移命令时,出现以下错误。Illuminate\Database\QueryException:SQLSTATE[42000]:语法错误或访问冲突:1067“valid_to”的默认值无效(SQL:创建表quarters(quarter_idint unsigned not null,year int unsigned not null,quarter_numint unsigned not null,valid_fromtimestamp not null,valid_totimestamp not null, description varchar(255) null, created_attimestamp null, updated_attimestamp null) 默认字符集 utf8mb4 collate 'utf8mb4_unicode_ci')这是 Eloquent 生成的 SQL:CREATE TABLE `quarters`(    `quarter_id` INT UNSIGNED NOT NULL,    `year` INT UNSIGNED NOT NULL,    `quarter_num` INT UNSIGNED NOT NULL,    `valid_from` TIMESTAMP NOT NULL,    `valid_to` TIMESTAMP NOT NULL,    `description` VARCHAR(255) NULL,    `created_at` TIMESTAMP NULL,    `updated_at` TIMESTAMP NULL) DEFAULT CHARACTER SET utf8mb4 COLLATE 'utf8mb4_unicode_ci'奇怪的是,如果我注释掉该valid_to行,那么它会创建没有错误的表。但是 的定义与valid_to100% 相似valid_from,并且它不会为valid_from列抛出该错误。实际上,数据库似乎不允许两timestamp列!
查看完整描述

2 回答

?
慕田峪9158850

TA贡献1794条经验 获得超7个赞

我通过将列的类型从 更改为 解决了我的timestamp问题dateTime。因此,如下更改表定义解决了我的问题,因为我需要一个日期和时间:


Schema::create('quarters', function (Blueprint $table) {

            $table->integer('quarter_id')->unsigned();

            $table->integer('year')->unsigned();

            $table->integer('quarter_num')->unsigned();

            $table->dateTime('valid_from');

            $table->dateTime('valid_to');            

            $table->string('description')->nullable();

            $table->timestamps();

            $table->primary('quarter_id');

        });

但是,我仍然很想知道我们如何not null在一个表中拥有多个时间戳列。


查看完整回答
反对 回复 2022-06-17
?
猛跑小猪

TA贡献1858条经验 获得超8个赞

MySql 和/或 MariaDB 中时间戳默认值的默认行为对于第一个时间戳声明与后续时间戳不同。

MariaDB 对于在特定表中使用 TIMESTAMP 数据类型的第一列具有特殊行为。对于特定表中使用 TIMESTAMP 数据类型的第一列,MariaDB 自动为该列分配以下属性:

更新 CURRENT_TIMESTAMP 时的默认 CURRENT_TIMESTAMP

这意味着如果在 INSERT 或 UPDATE 查询中没有显式地为该列分配值,那么 MariaDB 将使用当前日期和时间自动初始化该列的值。

通过为列指定 DEFAULT CURRENT_TIMESTAMP 和 ON UPDATE CURRENT_TIMESTAMP 子句,也可以为使用 TIMESTAMP 数据类型的列显式启用 INSERT 和 UPDATE 查询的这种自动初始化。在这些子句中,接受 CURRENT_TIMESTAMP 的任何同义词,包括 CURRENT_TIMESTAMP()、NOW()、LOCALTIME、LOCALTIME()、LOCALTIMESTAMP 和 LOCALTIMESTAMP()。

https://mariadb.com/kb/en/library/timestamp/

因此,第一个时间戳 ( valid_from) 获取 的自动默认值CURRENT_TIMESTAMP,这是不可为空的时间戳字段的可接受默认值。第二个字段获得不同的自动默认值,这似乎是数据库无法接受的。

解决当前问题的方法可能是遵循 MariaDB 的建议,并使用显式CURRENT_TIMESTAMP作为第二个时间戳的默认值(或两者兼而有之)。在 Laravel 中,这可能类似于$table->timestamp('valid_to')->useCurrent();.

在这方面需要注意的重要一点是,您最终选择的解决方案(使用日期时间而不是时间戳)可能是解决问题的更恰当的解决方案:时间戳是一种奇怪的数据类型,主要用作元数据. 特别是在 Mysql 和 MariaDB 中,它们天生就遭受“2038 年问题”的困扰,这对于 created_at 或 updated_at 字段再过 18 年左右都不是问题,但当 valid_to 可能在未来几年时可能会出现问题。这只是对不直观的自动默认值的补充......


查看完整回答
反对 回复 2022-06-17
  • 2 回答
  • 0 关注
  • 165 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信