MySQL没有给出默认值时,时间戳的默认值无效。

时间:2016-02-06 04:21:56

标签: mysql mysql-error-1067

查看以下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完全相同,而且我没有得到任何例外。

3 个答案:

答案 0 :(得分:9)

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

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

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

    然而,第二个非空时间戳列的默认值将是&00; 00:00:00'如果您没有明确定义默认值。

    请参阅this blog post for more details

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

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

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

答案 1 :(得分:4)

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

答案 2 :(得分:1)

引用2000年以来的文章并没有真正的帮助,因为从那时起已经发生了很多变化,并且可能不再适用。正如其他相关问题中已经提到的那样,TIMESTAMP值引用相对于UTC 1970年1月1日的特定时间点。相反,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。无论为数据库或连接设置了什么时区,DATETIME值始终保持在2018-01-12 14:00:00

因此,为了跟踪何时发生某事或何时/应该发生某事,TIMESTAMP是必经之路。如果您只想存储与时区无关的固定日期时间,请使用DATETIME(例如,用户应在凌晨2点收到一封电子邮件,因为每个人的凌晨2点都一样)。