【问题标题】:mysql and Python: does not allow two timestamp columnsmysql 和 Python:不允许有两个时间戳列
【发布时间】:2014-07-01 13:31:12
【问题描述】:

我在使用 Python、MySQL 和创建包含两个时间戳列的表时遇到问题。

通过 Python 并使用 MySQLDB 执行以下 SQL:

CREATE TABLE test_db.test_with_two_datetime_columns (
    `first_datetime_field` TIMESTAMP(6) NOT NULL DEFAULT 0,
    `second_datetime_field` TIMESTAMP(6) NOT NULL DEFAULT 0
) ENGINE=InnoDB 

我收到错误 (1067, Invalid default value for 'first_datetime_field'),而我可以在 MySQL CLI 中轻松触发以下相等命令:

$ mysql -h localhost

> CREATE TABLE test_db.test_with_two_datetime_columns (
      `first_datetime_field` TIMESTAMP(6) NOT NULL DEFAULT 0,
      `second_datetime_field` TIMESTAMP(6) NOT NULL DEFAULT 0
  ) ENGINE=InnoDB;
Query OK, 0 rows affected (0.01 sec)

同样通过 Sequel Pro,上面的命令也能正常执行。

所以我猜问题出在MySQLDB(又名MySQL-Python),但这看起来很奇怪

我正在使用MySQL 5.6.17MySQL-Python 1.2.5Python 2.7

【问题讨论】:

    标签: python mysql mysql-python


    【解决方案1】:

    我使用https://stackoverflow.com/a/22860449/1362628 的一个想法解决了问题,将默认值更改为null 并允许条目为null

    CREATE TABLE test_db.test_with_two_datetime_columns (
        `first_datetime_field` TIMESTAMP(6) NULL DEFAULT NULL,
        `second_datetime_field` TIMESTAMP(6) NULL DEFAULT NULL
    ) ENGINE=InnoDB""")
    

    现在它工作正常。但问题是这些字段都不能参与primary key,因为它们可以包含null


    更新

    原来使用SELECT @@session.sql_mode我发现MySQLDB上的包装代码将sql_mode设置为TRADITIONALTRADITIONAL 扩展为STRICT_TRANS_TABLES, STRICT_ALL_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, TRADITIONAL, NO_AUTO_CREATE_USER, NO_ENGINE_SUBSTITUTION,其中NO_ZERO_IN_DATENO_ZERO_DATE 使上述错误出现。但从长远来看,我更喜欢上述解决方案,将缺失值表示为 null。

    【讨论】:

      【解决方案2】:

      这里可能有几个问题。

      我的猜测是 MySQLDB 无法将整数 0 识别为 DateTime 或 Timestamp 类型的列的有效值。恕我直言,MySQL 也不应该,但确实如此。您可以在服务器级别更改该行为。见NO_ZERO_DATE

      如果我处于你的位置,我会尝试类似的方法。

      CREATE TABLE test_with_two_datetime_columns (
          `first_datetime_field` TIMESTAMP(6) not null default '0000-00-00 00:00:00',
          `second_datetime_field` TIMESTAMP(6) not null default '0000-00-00 00:00:00',
          primary key (first_datetime_field, second_datetime_field)
      ) ENGINE=InnoDB ;
      

      在这种情况下,这些默认值实际上与整数 0 相同。一种替代方法是将两列默认为时间戳的最小值,“1970-01-01 00:00:01”。另一种是将一列默认为 current_timestamp。 (不是两列;MySQL 认为这是一个错误。)

      就我个人而言,我不喜欢“全是球”的时间戳。 “所有球”是一个奇怪的时间戳——从词汇上讲,它不在 UTC 时间 '1970-01-01 00:00:01' 到 UTC 时间 '2038-01-19 03:14:07' 的定义范围内。但你必须找到自己的舒适度。

      【讨论】:

      • 是的,我试过了,但没有成功。我仍然收到 (1067, "Invalid default value for 'first_datetime_field'") 错误。默认为 current_timestamp 并不是一个真正的选择,因为如果我们的代码中有错误,默认时间戳可以隐藏它。
      • 默认值为“1970-01-01 00:00:01”时是否会出现该错误?也许需要向 MySQLDB 报告错误。
      • 是的,我明白了。我会向 MySQLDB 报告错误。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-28
      • 1970-01-01
      • 1970-01-01
      • 2017-11-27
      • 1970-01-01
      • 2018-03-05
      相关资源
      最近更新 更多