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

Bri*_*ght 851 mysql datetime

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

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

seb*_*ert 823

重要编辑: 现在可以通过自MySQL 5.6.5以来的DATETIME字段来实现这一点,看看下面的其他帖子 ......

以前的版本不能用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>
Run Code Online (Sandbox Code Playgroud)

**CAVEAT:如果您默认定义CURRENT_TIMESTAMP为ON的列,则需要始终为此列指定值,否则该值将在更新时自动重置为"now()".这意味着如果您不希望更改该值,则您的UPDATE语句必须包含"[您的列名] = [您的列名]"(或其他一些值),否则该值将变为"now()".很奇怪,但也是如此.我希望这有帮助.我使用的是5.5.56-MariaDB**

  • 值得注意的是,datetime的范围是1000-9999,但**时间戳的范围仅为1970-2038**.如果您的系统必须存储生日,或者您必须处理类似30年抵押贷款的付款计划,这可能是一个问题.http://dev.mysql.com/doc/refman/5.0/en/datetime.html (389认同)
  • 也要小心时间戳,因为它会神奇地自动更新...请参阅下一个答案http://stackoverflow.com/a/1483959/233906 (12认同)
  • **版本5.6.5可以**,请参阅Gustav的答案(我知道你的答案是在MySQL还是5.0的时候发布的!) (6认同)
  • @Kip,嗨,**'DATE`**列可以有一个默认值吗?(不是'datetime`专栏). (4认同)

Gus*_*ram 570

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

CREATE TABLE foo (
    `creation_time`     DATETIME DEFAULT CURRENT_TIMESTAMP,
    `modification_time` DATETIME ON UPDATE CURRENT_TIMESTAMP
)
Run Code Online (Sandbox Code Playgroud)

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

  • 只是一个注释 - 这对'date`不起作用 (7认同)
  • 'menu_creation_time'的默认值无效 (3认同)
  • @FernandoTrindade 您需要 MySQL 5.6.5 或更高版本。你可以在这里看到它的工作:http://sqlfiddle.com/#!9/dd2be (2认同)
  • 我认为“ON UPDATE”语法是错误的。根据 https://dev.mysql.com/doc/refman/5.6/en/timestamp-initialization.html 应该是`dt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP` (2认同)

小智 144

MySQL(版本5.6.5之前)不允许将函数用于默认的DateTime值.TIMESTAMP由于其奇怪的行为而不适用,因此不建议用作输入数据.(请参阅MySQL数据类型默认值.)

也就是说,您可以通过创建触发器来实现此目的.

我有一个DateTime类型的DateCreated字段的表.我在该表"Before Insert"和" SET NEW.DateCreated=NOW()" 上创建了一个触发器,它的效果非常好.

我希望这有助于某人.

  • 在插入foo之前创建TRIGGER trigger_foo_SetCreatedAt每个行设置NEW.created_at = UTC_TIMESTAMP(); (20认同)
  • 您可能只想设置默认值`IF NEW.created_at IS NOT NULL` (8认同)
  • 你可能最好使用时间戳而不是触发器来实现未来的健全(维护).虽然这是一个解决方案,但这对于触发器来说太简单了. (5认同)

Joh*_*son 131

对我来说,触发方法效果最好,但我发现了这种方法的障碍.考虑在插入时将日期字段设置为当前时间的基本触发器:

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

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

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

会发生什么是触发器会立即覆盖您提供的字段值,因此设置非当前时间的唯一方法是跟进UPDATE语句 - 哎呀!要在提供值时覆盖此行为,请使用IFNULL运算符尝试此略微修改的触发器:

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

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

  • +1用于在插入时覆盖显式用户值来确认警告. (5认同)
  • 在MySQL 5.5中,IFNULL不适用于DATETIME; 使用上面的触发器,`dateAdded`将显示所有'0000-00-00 00:00:00'.使用它可以解决这个问题:`每个行如果NEW.dateAdded = 0那么设置NEW.dateAdded = NOW(); 结束IF;` (4认同)
  • 我个人认为这是最好的方式.TIMESTAMP确实有奇怪的行为,我永远不会编写具有2038年限制的代码. (2认同)

小智 27

我能够在我的桌子上使用这个具有两个日期时间字段的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;
Run Code Online (Sandbox Code Playgroud)

这可以像你期望的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();
Run Code Online (Sandbox Code Playgroud)

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


小智 23

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

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;
Run Code Online (Sandbox Code Playgroud)


Aug*_*wan 18

对于那些在MySQL中设置默认DATETIME值的人而言,我确切地知道你的感受/感受.所以这是:

ALTER TABLE  `table_name` CHANGE `column_name` DATETIME NOT NULL DEFAULT 0
Run Code Online (Sandbox Code Playgroud)

仔细观察我没有0附近添加单引号/双引号

解决这个问题后,我真的在跳跃:D

  • 它不会插入当前时间.它会插入'0000-00-00 00:00:00'. (8认同)
  • 我没有说它设定了当前的时间.许多人正试图设置一个默认的零值,但它只是不起作用.我们需要消除报价.由于这一发现造成了大量的时间和挫折,我想与社区分享.像您这样的人对失去与其他人分享有用信息感兴趣的用户负责.我认真地看不出任何理由得到-1!随你. (8认同)
  • 使用DATETIME NOT NULL可以实现相同的效果. (2认同)

小智 14

MySQL 5.6修复了这个问题.

ALTER TABLE mytable CHANGE mydate datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP'
Run Code Online (Sandbox Code Playgroud)


Kin*_*xit 13

这确实是一个可怕的消息.这是一个很长的未决错误/功能请求.该讨论还讨论了时间戳数据类型的局限性.

我真的很想知道实现这个问题是什么问题.

  • 它发生了:http://dev.mysql.com/doc/refman/5.6/en/timestamp-initialization.html (6认同)

Sav*_*ake 13

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

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

ALTER TABLE <TABLE_NAME> 
CHANGE COLUMN <COLUMN_NAME> <COLUMN_NAME> DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP;
Run Code Online (Sandbox Code Playgroud)

要将默认值更改为"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';
Run Code Online (Sandbox Code Playgroud)


Gvs*_*hil 10

与 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;
Run Code Online (Sandbox Code Playgroud)


Evh*_*vhz 9

我正在运行MySql Server 5.7.11和这句话:

ALTER TABLE table_name CHANGE date_column datetime NOT NULL DEFAULT '0000-00-00 00:00:00'
Run Code Online (Sandbox Code Playgroud)

不是工作.但是以下内容:

ALTER TABLE table_name CHANGE date_column datetime NOT NULL DEFAULT '1000-01-01 00:00:00'
Run Code Online (Sandbox Code Playgroud)

只是工作.

作为旁注,它在mysql文档中提到:

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

即使他们也说:

无效的DATE,DATETIME或TIMESTAMP值将转换为相应类型的"零"值('0000-00-00'或'0000-00-00 00:00:00').


Ker*_*elM 7

您可以使用now()来设置datetime列的值,但请记住,您不能将其用作默认值.

  • 真正.我刚刚尝试使用并收到错误"错误代码:1067.默认值无效.".那么答案是什么?;-) (4认同)

Fab*_*ian 7

对于使用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年后更新并且该限制被删除了怎么办?我不确定这是否可能,但只是一个想法. (2认同)

小智 7

在定义多行触发器时,必须更改分隔符,因为MySQL编译器将以分号作为触发结束并生成错误.例如

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


Vij*_* VP 5

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


小智 5

虽然您无法DATETIME在默认定义中执行此操作,但您可以在insert语句中简单地包含select语句,如下所示:

INSERT INTO Yourtable (Field1, YourDateField) VALUES('val1', (select now()))
Run Code Online (Sandbox Code Playgroud)

请注意表格周围缺少引号.

对于MySQL 5.5

  • now()而不是(select now())就足够了 (10认同)

小智 5

以下是如何在 MySQL 5.1 上执行此操作:

ALTER TABLE `table_name` CHANGE `column_name` `column_name` 
TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;
Run Code Online (Sandbox Code Playgroud)

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

  • CHANGE 也用于重命名字段。第一列名称是“旧”,第二列名称是“新”。如果您不更改字段的名称,它看起来是多余的。如果太不美观,请尝试修改。 (5认同)

Bha*_*iya 5

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

 CREATE TABLE bar(
        `create_time` TIMESTAMP CURRENT_TIMESTAMP,
        `update_time` TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
    )
Run Code Online (Sandbox Code Playgroud)