【问题标题】:How do you set a default value for a MySQL Datetime column?如何为 MySQL 日期时间列设置默认值?
【发布时间】:2010-09-15 04:29:21
【问题描述】:

如何为 MySQL Datetime 列设置默认值?

在 SQL Server 中,它是 getdate()。 MySQL 的等价物是什么?如果这是一个因素,我正在使用 MySQL 5.x。

【问题讨论】:

  • 我在我的 mysql 表中使用 CURRENT_TIMESTAMP(不在查询中),也许这也有帮助。
  • 此功能现已添加到 MySQL 5.6.5。希望这可以帮助某人。 optimize-this.blogspot.co.uk/2012/04/…
  • @GhostInTheSecureShell 非常有责任安装它,至少在 Debian 上是这样,但绝对是一个很棒的功能。我认为最终所有这些“两个 CURRENT_TIMESTAMP”的问题都会得到缓解!
  • 它是 now() 函数,否则您可以在列级别使用默认设置。

标签: mysql datetime


【解决方案1】:

重要编辑:MySQL 5.6.5 开始,现在可以使用 DATETIME 字段来实现这一点,看看下面的 other post...

以前的版本不能用 DATETIME 做到这一点...

但您可以使用 TIMESTAMP 来做到这一点:

mysql> create table test (str varchar(32), ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
Query OK, 0 rows affected (0.00 sec)

mysql> desc test;
+-------+-------------+------+-----+-------------------+-------+
| Field | Type        | Null | Key | Default           | Extra |
+-------+-------------+------+-----+-------------------+-------+
| str   | varchar(32) | YES  |     | NULL              |       | 
| ts    | timestamp   | NO   |     | CURRENT_TIMESTAMP |       | 
+-------+-------------+------+-----+-------------------+-------+
2 rows in set (0.00 sec)

mysql> insert into test (str) values ("demo");
Query OK, 1 row affected (0.00 sec)

mysql> select * from test;
+------+---------------------+
| str  | ts                  |
+------+---------------------+
| demo | 2008-10-03 22:59:52 | 
+------+---------------------+
1 row in set (0.00 sec)

mysql>

CAVEAT: 如果您定义一个默认为 CURRENT_TIMESTAMP ON 的列,您需要始终为该列指定一个值,否则该值将自动重置为“now()”在更新。这意味着如果您不想更改值,您的 UPDATE 语句必须包含“[您的列名] = [您的列名]”(或其他值),否则该值将变为“now()”。很奇怪,但确实如此。我正在使用 5.5.56-MariaDB

【讨论】:

  • 需要注意的是,datetime 的范围是 1000-9999,但 timestamp 的范围只有 1970-2038。如果您的系统必须存储生日,或者您必须处理诸如 30 年抵押贷款的付款计划之类的事情,这可能会成为问题。 dev.mysql.com/doc/refman/5.0/en/datetime.html
  • 要小心时间戳,因为它会神奇地自动更新...查看下一个答案stackoverflow.com/a/1483959/233906
  • 从 5.6.5 版开始可能的,请参阅下面 Gustav 的回答(我知道你的回答是在 MySQL 还是 5.0 时发布的!)
  • @Kip,嗨,是否可以为 DATE 列设置默认值? (不是datetime 列)。
  • ti 似乎无法用于 DATE 列:您必须使用 DATETIME 数据类型
【解决方案2】:

在 5.6.5 版本中,可以在 datetime 列上设置默认值,甚至可以创建在行更新时会更新的列。类型定义:

CREATE TABLE foo (
    `creation_time`     DATETIME DEFAULT CURRENT_TIMESTAMP,
    `modification_time` DATETIME ON UPDATE CURRENT_TIMESTAMP
)

参考: http://optimize-this.blogspot.com/2012/04/datetime-default-now-finally-available.html

【讨论】:

  • “menu_creation_time”的默认值无效
  • @FernandoTrindade 您需要 MySQL 5.6.5 或更高版本。你可以在这里看到它的工作原理:sqlfiddle.com/#!9/dd2be
  • @GustavBertram,我使用的是 5.6.22 版,但仍然出现如下错误:CREATE TABLE tbl ( InsertDate DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, UpdateDate TIMESTAMP NULL ON UPDATE CURRENT_TIMESTAMP(6) );错误代码:1294。“UpdateDate”列的 ON UPDATE 子句无效
  • @ManishSapkal 您使用的是 TIMESTAMP,而不是 DATETIME。另外,不要将其设为 NULL。
  • 我认为“ON UPDATE”语法是错误的。根据dev.mysql.com/doc/refman/5.6/en/timestamp-initialization.html 应该是dt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
【解决方案3】:

MySQL (before version 5.6.5) 不允许函数用于默认 DateTime 值。 TIMESTAMP 由于其奇怪的行为而不适合,因此不建议将其用作输入数据。 (见MySQL Data Type Defaults。)

也就是说,你可以做到这一点by creating a Trigger

我有一个包含 DateTime 类型的 DateCreated 字段的表。我在该表“插入前”和“SET NEW.DateCreated=NOW()”上创建了一个触发器,效果很好。

我希望这对某人有所帮助。

【讨论】:

  • CREATE TRIGGER trigger_foo_SetCreatedAt BEFORE INSERT ON foo FOR EACH ROW SET NEW.created_at = UTC_TIMESTAMP();
  • 您可能最好使用时间戳而不是触发器来确保未来的健全性(维护)。尽管这是一个解决方案,但这对于触发器来说太微不足道了。
  • 您可能只想设置默认值 IF NEW.created_at IS NOT NULL
【解决方案4】:

对我来说,触发方法效果最好,但我发现该方法存在问题。考虑在插入时将日期字段设置为当前时间的基本触发器:

CREATE TRIGGER myTable_OnInsert BEFORE INSERT ON `tblMyTable`
    FOR EACH ROW SET NEW.dateAdded = NOW();

这通常很好,但假设您想通过 INSERT 语句手动设置字段,如下所示:

INSERT INTO tblMyTable(name, dateAdded) VALUES('Alice', '2010-01-03 04:30:43');

发生的情况是触发器会立即覆盖您为该字段提供的值,因此设置非当前时间的唯一方法是跟进 UPDATE 语句——糟糕!要在提供值时覆盖此行为,请尝试使用 IFNULL 运算符稍作修改的触发器:

CREATE TRIGGER myTable_OnInsert BEFORE INSERT ON `tblMyTable`
    FOR EACH ROW SET NEW.dateAdded = IFNULL(NEW.dateAdded, NOW());

这提供了两全其美:您可以为您的日期列提供一个值,它将采用,否则它将默认为当前时间。相对于表定义中的 DEFAULT GETDATE() 等干净的东西,它仍然是贫民区,但我们越来越近了!

【讨论】:

  • +1 用于确认在插入时覆盖显式用户值的警告。
  • 我个人认为这是最好的方法。 TIMESTAMP 确实有奇怪的行为,我永远不会编写有 2038 年限制的代码。
  • 没关系,我想通了。忘记将字段设置为允许NULL。没有警告了。
  • 触发器是邪恶的!只有在没有其他方法可以做某事时才使用它们。最好升级到 5.6.x id,而不是使用触发器。
  • 在 MySQL 5.5 中,IFNULL 在 DATETIME 上不起作用;使用上述触发器,dateAdded 将显示所有“0000-00-00 00:00:00”。使用这个技巧:` FOR EACH ROW IF NEW.dateAdded = 0 THEN SET NEW.dateAdded = NOW();结束如果;`
【解决方案5】:

我能够在有两个日期时间字段的表上使用这个 alter 语句来解决这个问题。

ALTER TABLE `test_table`
  CHANGE COLUMN `created_dt` `created_dt` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',
  CHANGE COLUMN `updated_dt` `updated_dt` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;

这就像你期望 now() 函数一样工作。插入空值或忽略 created_dt 和 updated_dt 字段会在两个字段中产生完美的时间戳值。对行的任何更新都会更改 updated_dt。如果您通过 MySQL 查询浏览器插入记录,则需要多一步,即使用新时间戳处理 created_dt 的触发器。

CREATE TRIGGER trig_test_table_insert BEFORE INSERT ON `test_table`
    FOR EACH ROW SET NEW.created_dt = NOW();

触发器可以是任何你想要的我只是喜欢命名约定[trig]_[my_table_name]_[insert]

【讨论】:

  • 我的意思是说,如果您通过 MySQL 查询浏览器手动通过网格插入记录,而不需要 insert() 语句,则需要触发器。如果您总是使用插入语句,则完全不需要触发器。
  • 哎呀!我的意思是触发器(名称)可以是任何你想要的,因为触发器名称根本不会影响功能。大多数人都知道这一点,但一些刚接触 MySQL 的人可能不知道......
  • 哎呀,抱歉缺少换行符。使用分号标记每行的结尾。
【解决方案6】:

您可以使用触发器来执行此类操作。

CREATE TABLE `MyTable` (
`MyTable_ID`  int UNSIGNED NOT NULL AUTO_INCREMENT ,
`MyData`  varchar(10) NOT NULL ,
`CreationDate`  datetime NULL ,
`UpdateDate`  datetime NULL ,
PRIMARY KEY (`MyTable_ID`)
)
;

CREATE TRIGGER `MyTable_INSERT` BEFORE INSERT ON `MyTable`
FOR EACH ROW BEGIN
        -- Set the creation date
    SET new.CreationDate = now();

        -- Set the udpate date
    Set new.UpdateDate = now();
END;

CREATE TRIGGER `MyTable_UPDATE` BEFORE UPDATE ON `MyTable`
FOR EACH ROW BEGIN
        -- Set the udpate date
    Set new.UpdateDate = now();
END;

【讨论】:

    【解决方案7】:

    对于所有试图在 MySQL 中设置默认 DATETIME 值的人来说,我完全了解您的感受/感受。所以这里是:

    ALTER TABLE  `table_name` CHANGE `column_name` DATETIME NOT NULL DEFAULT 0
    

    仔细观察我没有在0

    周围加单引号/双引号

    解决了这个问题后我真的跳起来了:D

    【讨论】:

    • 它不插入不是当前时间。它将插入 '0000-00-00 00:00:00' 。
    • 我没有说它设置当前时间。许多人曾经/正在尝试设置默认的零值,但它不起作用。我们需要消除引号。由于这一发现引起了很多时间和挫败感,我想与社区分享。像您这样的人要为用户失去与他人分享有用信息的兴趣负责。我真的看不出有任何理由得到-1!随便。
    • 使用 DATETIME NOT NULL 也可以达到同样的效果。
    • 示例 sql 命令中还有一个 ` 字符,我无法编辑出来,因为它只能编辑一个字符。
    • 你的代码对我不起作用,这是起作用的ALTER TABLE zones MODIFY created datetime NOT NULL DEFAULT 0;
    【解决方案8】:

    如果你已经创建了表,那么你可以使用

    将默认值更改为当前日期时间

    ALTER TABLE <TABLE_NAME> 
    CHANGE COLUMN <COLUMN_NAME> <COLUMN_NAME> DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP;
    

    将默认值更改为 '2015-05-11 13:01:01'

    ALTER TABLE <TABLE_NAME> 
    CHANGE COLUMN <COLUMN_NAME> <COLUMN_NAME> DATETIME NOT NULL DEFAULT '2015-05-11 13:01:01';
    

    【讨论】:

      【解决方案9】:

      MySQL 5.6 has fixed this problem.

      ALTER TABLE mytable CHANGE mydate datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP'
      

      【讨论】:

        【解决方案10】:

        这确实是个可怕的消息。here is a long pending bug/feature request for this。该讨论还谈到了时间戳数据类型的限制。

        我很想知道实现这个东西有什么问题。

        【解决方案11】:

        我运行的是MySql Server 5.7.11和这句话:

        ALTER TABLE table_name CHANGE date_column datetime NOT NULL DEFAULT '0000-00-00 00:00:00'
        

        没有工作。但以下:

        ALTER TABLE table_name CHANGE date_column datetime NOT NULL DEFAULT '1000-01-01 00:00:00'
        

        正常工作

        作为一个旁注,在mysql docs中提到:

        DATE 类型用于具有日期部分但没有时间部分的值。 MySQL 以 'YYYY-MM-DD' 格式检索和显示 DATE 值。支持的范围是“1000-01-01”到“9999-12-31”。

        即使他们也说:

        无效的 DATE、DATETIME 或 TIMESTAMP 值将转换为相应类型的“零”值('0000-00-00' 或 '0000-00-00 00:00:00')。

        【讨论】:

          【解决方案12】:

          您可以使用 now() 来设置日期时间列的值,但请记住,您不能将其用作默认值。

          【讨论】:

          • 真的。我刚刚尝试使用现在并得到一个错误“错误代码:1067。无效的默认值。”。那么答案是什么? ;-)
          • 这是破坏 MySQL 5.5 和 5.6 版本的最佳解决方案。对于 5.5 版,预先确定 NOW() 的值并稍后将其用于插入。对于 5.6 版,只需将 NOW() 设置为默认值。
          【解决方案13】:

          对于所有使用 TIMESTAMP 列作为解决方案的人,我想从手册中获得以下限制:

          http://dev.mysql.com/doc/refman/5.0/en/datetime.html

          “TIMESTAMP 数据类型的范围为 '1970-01-01 00:00:01' UTC 到 '2038-01-19 03:14:07' UTC。它有不同的属性,取决于 MySQL 版本和服务器运行的 SQL 模式。这些属性将在本节后面介绍。"

          所以这显然会在大约 28 年后破坏您的软件。

          我相信数据库方面的唯一解决方案是使用其他答案中提到的触发器。

          【讨论】:

          • 如果 MySQL 在 20 年后更新并且取消了该限制会怎样?我不确定这是否可能,但只是一个想法。
          • @NessDan looool
          【解决方案14】:

          在定义多行触发器时,必须更改分隔符,因为分号将被 MySQL 编译器视为触发器的结尾并产生错误。 例如

          DELIMITER //
          CREATE TRIGGER `MyTable_UPDATE` BEFORE UPDATE ON `MyTable`
          FOR EACH ROW BEGIN
                  -- Set the udpate date
              Set new.UpdateDate = now();
          END//
          DELIMITER ;
          

          【讨论】:

            【解决方案15】:

            在 MySQL 8.x 上运行良好

            CREATE TABLE `users` (
                  `id` int(11) NOT NULL AUTO_INCREMENT,
                  `dateCreated` datetime DEFAULT CURRENT_TIMESTAMP,
                  `dateUpdated` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                  PRIMARY KEY (`id`),
                  UNIQUE KEY `mobile_UNIQUE` (`mobile`)
                ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
            

            【讨论】:

              【解决方案16】:

              虽然您不能在默认定义中使用 DATETIME 执行此操作,但您可以像这样在插入语句中简单地合并一个 select 语句:

              INSERT INTO Yourtable (Field1, YourDateField) VALUES('val1', (select now()))
              

              请注意表格周围没有引号。

              对于 MySQL 5.5

              【讨论】:

                【解决方案17】:

                如果您尝试将默认值设置为 NOW(),我认为 MySQL 不支持。在 MySQL 中,您不能使用函数或表达式作为任何类型列的默认值,但 TIMESTAMP 数据类型列除外,您可以为其指定 CURRENT_TIMESTAMP 作为默认值。

                【讨论】:

                  【解决方案18】:

                  这是在 MySQL 5.1 上的操作方法:

                  ALTER TABLE `table_name` CHANGE `column_name` `column_name` 
                  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;
                  

                  我不知道为什么你必须输入两次列名。

                  【讨论】:

                  • CHANGE 也用于重命名字段。第一列名称是“旧”,第二列名称是“新”。如果您不更改字段的名称,它看起来是多余的。如果太不美观,请尝试 MODIFY。
                  【解决方案19】:

                  我认为在 mysql 中很简单,因为 mysql 的内置函数 now() 给出了当前时间(插入的时间)。

                  所以你的查询应该看起来相似

                  CREATE TABLE defaultforTime(
                      `creation_time`     DATETIME DEFAULT CURRENT_TIMESTAMP,
                      `modification_time` DATETIME default now()
                  );
                  

                  谢谢。

                  【讨论】:

                    【解决方案20】:

                    如果您设置ON UPDATE CURRENT_TIMESTAMP,则表中行数据更新时将采用当前时间。

                     CREATE TABLE bar(
                            `create_time` TIMESTAMP CURRENT_TIMESTAMP,
                            `update_time` TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
                        )
                    

                    【讨论】:

                      【解决方案21】:
                      CREATE TABLE `testtable` (
                          `id` INT(10) NULL DEFAULT NULL,
                          `colname` DATETIME NULL DEFAULT '1999-12-12 12:12:12'
                      )
                      

                      在上面创建'testtable'的查询中,我使用'1999-12-12 12:12:12'作为DATETIME列colname的默认值

                      【讨论】:

                        【解决方案22】:

                        使用以下代码

                        DELIMITER $$
                        
                            CREATE TRIGGER bu_table1_each BEFORE UPDATE ON table1 FOR EACH ROW
                            BEGIN
                              SET new.datefield = NOW();
                            END $$
                        
                            DELIMITER ;
                        

                        【讨论】:

                          【解决方案23】:

                          如果您尝试将默认值设置为 NOW(),MySQL 支持您必须更改该列的类型 TIMESTAMP 而不是 DATETIME。 TIMESTAMP 默认为当前日期和时间..我认为它会解决您的问题..

                          【讨论】:

                            【解决方案24】:

                            例如,如果我有一个名为“site”的表,其中包含一个 created_at 和一个 update_at 列,它们都是 DATETIME 并且需要现在的默认值,我可以执行以下 sql 来实现这一点。

                            ALTER TABLE `site` CHANGE `created_at` `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP; ALTER TABLE `site` CHANGE `created_at` `created_at` DATETIME NULL DEFAULT NULL; ALTER TABLE `site` CHANGE `updated_at` `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP; ALTER TABLE `site` CHANGE `updated_at` `updated_at` DATETIME NULL DEFAULT NULL;

                            语句的顺序很重要,因为一个表不能有两个 TIMESTAMP 类型的列,默认值为 CUREENT TIMESTAMP

                            【讨论】:

                              【解决方案25】:

                              这是我的触发器示例:

                              /************ ROLE ************/
                              drop table if exists `role`;
                              create table `role` (
                                  `id_role` bigint(20) unsigned not null auto_increment,
                                  `date_created` datetime,
                                  `date_deleted` datetime,
                                  `name` varchar(35) not null,
                                  `description` text,
                                  primary key (`id_role`)
                              ) comment='';
                              
                              drop trigger if exists `role_date_created`;
                              create trigger `role_date_created` before insert
                                  on `role`
                                  for each row 
                                  set new.`date_created` = now();

                              【讨论】:

                                【解决方案26】:

                                您可以解析默认时间戳。首先考虑您使用的是哪个字符集,例如,如果您采用 utf8,则此字符集支持所有语言,如果您采用 laten1,则此字符集仅支持英语。 Next setp 如果您在任何项目下工作,您应该知道客户时区并选择您是客户区。此步骤是强制性的。

                                【讨论】:

                                • DateTime 列不能有默认值。它记录了“功能”。并非所有开发人员都有权更改其字符编码。并且将服务器设置为它的 clients 时区通常是不可能的,尤其是当客户端并非全部本地到单个时区时。
                                猜你喜欢
                                • 1970-01-01
                                • 1970-01-01
                                • 1970-01-01
                                • 1970-01-01
                                • 2017-07-06
                                • 2023-03-24
                                • 1970-01-01
                                • 1970-01-01
                                相关资源
                                最近更新 更多