MySQL 未提供默认值时,时间戳的默认值无效。

MySQL Invalid default value for timestamp when no default value is given.

看下面sql.

CREATE SCHEMA IF NOT EXISTS `scheduler`;
USE `scheduler` ;
CREATE TABLE IF NOT EXISTS `scheduler`.`JobHistory` (
  `Id` INT NOT NULL AUTO_INCREMENT,
  `Job` INT NOT NULL,
  `StartTime` TIMESTAMP NOT NULL,
  `FinishTime` TIMESTAMP NOT NULL,
  PRIMARY KEY (`Id`),
  INDEX `fk_JobHistory_Job_idx` (`Job` ASC));

正在投掷ErrorCode: 1067. Invalid default value for 'Finish Time' 但我没有为完成时间提供任何默认值,还有另一个时间戳 StartTime 完全相同,我没有得到任何例外。

您应该为 StartTime 和 FinishTime 列使用 DATETIME 数据类型。 TIMESTAMPS 有一个非常具体的用法。参见 http://www.sqlteam.com/article/timestamps-vs-datetime-data-types

虽然@jsnplank 是正确的,时间戳被区别对待并且您应该考虑对这 2 个特定列使用 datetime 数据类型,但是,他未能解释错误消息。

错误消息很可能是 mysql 在未提供默认值时如何处理时间戳字段以及您的 sql 模式设置的组合结果。

  1. 您将两个时间戳列都定义为非空,但没有设置任何特定的默认值。这意味着第一个时间戳列的默认值将是 current_timestamp() 并且每当记录更改时也将更新为 current_timestamp() 。这就是第一个时间戳字段不会生成错误消息的原因,无论这两个字段中的哪个是第一个。

    但是,如果您没有明确定义默认值,第二个非空时间戳列的默认值将为“0000-00-00 00:00:00”。

    参见 this blog post for more details

  2. 可能 no_zero_date sql 模式也在您的服务器上显式或作为严格 sql 模式的一部分启用。如果您想将“0000-00-00 00:00:00”设置为默认值或想将此值插入任何日期字段,此 sql 模式会生成错误。

因此,您可以在 table 中使用时间戳数据类型,但使第二个数据类型可为空或提供 0 或任何有效日期(例如纪元)作为明确的默认值。

由于您使用这些字段标记开始和结束日期,因此使用日期时间而不是时间戳作为数据类型可能是个好主意。

引用 2000 年的文章并没有多大帮助,因为从那时起已经发生了很多变化,可能不再适用。正如其他人在其他相关问题中已经提到的那样,TIMESTAMP 值引用了相对于 1970 年 1 月 1 日 UTC 的特定时间点。相反,DATETIME 值只存储一些日期和时间,而不参考任何时间点。它们更像是显示值,墙上的时钟向您显示一些值。如果您想跟踪某事发生的时间,2018-01-12 14:00:00 的日期时间在不同的时区可能是不同的时间。

另一方面,TIMESTAMP 始终存储为 UTC,当在日期时间函数中读取或使用时,会自动转换回连接或数据库的默认时区。因此,当您的连接设置为 +02:00 时,将存储在 TIMESTAMP 列中的实际值将是 2018-01-12 12:00:00 而不是 2018-01-12 14:00:00。然后当您阅读带有 +05:00 连接的专栏时,您将看到 2018-01-12 17:00:00。无论为数据库或连接设置什么时区,DATETIME 值将始终保持在 2018-01-12 14:00:00

因此,要跟踪某事何时发生或某事何时发生 will/should,TIMESTAMP 是必经之路。当您只想存储一个独立于时区的固定日期时间时,请使用 DATETIME(例如,用户应在凌晨 2 点收到一封电子邮件,因为凌晨 2 点对每个人来说都是一样的)。