8

看下面的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完全相同的时间戳,我没有得到任何例外。

4

3 回答 3

10

尽管@jsnplank 对时间戳的处理方式不同是正确的,并且您应该考虑对这两个特定列使用 datetime 数据类型,但是,他未能解释错误消息。

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

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

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

    有关详细信息,请参阅此博客文章

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

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

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

于 2016-02-06T04:58:28.577 回答
4

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

于 2016-02-06T04:26:29.343 回答
1

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

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

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

于 2019-01-20T19:36:21.257 回答