【问题标题】:Is it possible to create a column with a UNIX_TIMESTAMP default in MySQL?是否可以在 MySQL 中创建具有 UNIX_TIMESTAMP 默认值的列?
【发布时间】:2011-07-16 21:44:00
【问题描述】:

我正在尝试这样做,但似乎 MySQL 不允许我这样做。是否有解决此问题的方法,还是希望我始终在我的 INSERT 查询中包含该函数?

CREATE TABLE foo(
  created INT NOT NULL DEFAULT UNIX_TIMESTAMP()
)

我知道接受 CURRENT_TIMESTAMP 默认值的 TIMESTAMP 类型,但我的客户坚持在数据库中使用纪元时间。

【问题讨论】:

    标签: mysql sql database database-design database-schema


    【解决方案1】:

    MySQL实现TIMESTAMP数据类型的方式,其实就是在数据库中存储epoch时间。因此,如果要将其显示为 int,您可以使用默认为 CURRENT_TIMESTAMPTIMESTAMP 列并对其应用 UNIX_TIMESTAMP()

    CREATE TABLE foo(
      created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
    );
    
    insert into foo values (current_Date()),(now());
    
    select unix_timestamp(created) from foo;
    +-------------------------+
    | unix_timestamp(created) |
    +-------------------------+
    |              1300248000 |
    |              1300306959 |
    +-------------------------+
    2 rows in set (0.00 sec)
    

    但是,如果您确实希望列的数据类型为INT,您可以使用 R. Bemrose 的建议并通过触发器进行设置:

    CREATE TABLE foo(
      created INT NULL
    );
    
    delimiter $$
    
    create trigger tr_b_ins_foo before insert on foo for each row
    begin
      if (new.created is null)
      then
        set new.created = unix_timestamp();
      end if;
    end $$
    
    delimiter ;
    
    
    insert into foo values (unix_timestamp(current_Date())), (null);
    
    select created from foo;
    +------------+
    | created    |
    +------------+
    | 1300248000 |
    | 1300306995 |
    +------------+
    2 rows in set (0.00 sec)
    

    【讨论】:

    • 查询 TIMESTAMP 与 BIGINT 的性能是否存在差异?它实际上是作为字符串物理存储的,还是有效地存储? Tnx。
    • 任何选择数据类型的人都应该记住,TIMESTAMP 面向相同的 2038,但与 INT 相同。考虑存储在 UNSIGNED INT(11) 中的 UNIX_TIMESTAMP (Epoch) 的原因是将溢出错误推到下个世纪(BIGINT 甚至更远)。届时,随着新技术的出现,您的代码可能需要重写。然而,2038 年将在我们的许多人生中发生。我们今天构建的数据库在那个时候仍然可以作为遗留系统存在。 @JRun - 我希望 MySQL 中的 TIMESTAMP 在后端被视为 INT ,因为它具有相同的数字限制。
    • 我应该澄清一下——我上面的评论是相对于 MySQL 5.5 的。谁知道未来的版本会做什么。根据开发者文档:
    • 这里引用我的观点。请注意,该范围在数学上与“有符号”INT 相同。 “根据开发人员文档:TIMESTAMP 数据类型用于包含日期和时间部分的值。TIMESTAMP 的范围为 '1970-01-01 00:00:01' UTC 到 '2038-01-19 03:14 :07' UTC。”网址:dev.mysql.com/doc/refman/5.5/en/datetime.html
    【解决方案2】:

    来自the documentation

    除了一个例外,默认值 必须是常数;它不能是 函数或表达式。这意味着, 例如,您不能设置 日期列的默认值为 NOW() 等函数的值或 当前的日期。例外是 您可以将 CURRENT_TIMESTAMP 指定为 TIMESTAMP 列的默认值。

    【讨论】:

      【解决方案3】:

      您可以为此创建触发器。

      用于插入

      • 查询

      CREATE TRIGGER {trigger_name} BEFORE INSERT ON {table_name} FOR EACH ROW SET new.{field_name} = UNIX_TIMESTAMP(NOW());

      • 在这种情况下

      CREATE TRIGGER my_trigger_name_1 BEFORE INSERT ON foo FOR EACH ROW SET new.created = UNIX_TIMESTAMP(NOW());

      更新

      • 查询

      CREATE TRIGGER {trigger_name} BEFORE UPDATE ON {table_name} FOR EACH ROW SET new.{field_name} = UNIX_TIMESTAMP(NOW());

      • 在这种情况下

      CREATE TRIGGER my_trigger_name_2 BEFORE UPDATE ON foo FOR EACH ROW SET new.created = UNIX_TIMESTAMP(NOW());

      注意:我不知道MYSQL TRIGGER

      的性能

      请浏览这些链接

      1. Identify some of the drawback of implementing sql server triggers

      2. Using Triggers

      【讨论】:

        【解决方案4】:

        好吧,如果 MySQL 不允许您直接执行此操作,您始终可以使用 BEFORE INSERT... FOR EACH ROW trigger 执行此操作。

        【讨论】:

          【解决方案5】:

          现在,使用 MySQL v8+,您可以在括号中执行此操作:

          CREATE TABLE t1 (
            -- literal defaults
            i INT         DEFAULT 0,
            c VARCHAR(10) DEFAULT '',
            -- expression defaults
            f FLOAT       DEFAULT (RAND() * RAND()),
            b BINARY(16)  DEFAULT (UUID_TO_BIN(UUID())),
            d DATE        DEFAULT (CURRENT_DATE + INTERVAL 1 YEAR),
            p POINT       DEFAULT (Point(0,0)),
            j JSON        DEFAULT (JSON_ARRAY())
          );
          

          docs

          【讨论】:

          • 然后呢?您是否测试过UNIX_TIMESTAMP() 而不是引用与原始 Q 无关的内容?请相应地编辑您的 A。
          【解决方案6】:

          作为ktretyak's answer,在 MySQL v8+ 中,您可以使用括号来实现。

          CREATE TABLE foo(
            created INT NOT NULL DEFAULT (UNIX_TIMESTAMP())
          )
          

          插入后,您可以看到它正常工作。
          (在 MySQL 8.0.26 上测试 + 仅文本颜色修补)

          您也可以使用表达式。
          检查ktretyak's answer

          我写这个答案而不是评论或编辑答案(尝试和拒绝)
          因为缺乏 REPUTATION,所以现在使用括号是很好的解决方案。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-05-25
            • 1970-01-01
            • 2018-09-26
            • 1970-01-01
            相关资源
            最近更新 更多