将NOW()设置为datetime数据类型的默认值?

215

我有一个名为users的表格中有两个列registerDate和lastVisitDate,它们都是datetime数据类型。我想要做以下操作:

  1. 将registerDate默认值设置为MySQL NOW()
  2. 将lastVisitDate默认值设置为0000-00-00 00:00:00,而不是默认使用null。

因为该表已经存在并且有现有记录,所以我想使用"修改表"方法。我尝试了下面这两段代码,但都不起作用。

ALTER TABLE users MODIFY registerDate datetime DEFAULT NOW()
ALTER TABLE users MODIFY registerDate datetime DEFAULT CURRENT_TIMESTAMP;

我遇到了错误:ERROR 1067 (42000): Invalid default value for 'registerDate'

在MySQL中,是否可以将默认的日期时间值设置为NOW()?


4
ALTER TABLE users MODIFY dateTime TIMESTAMP DEFAULT CURRENT_TIMESTAMP。你在两次尝试中都没有定义字段的数据类型。 - Shakti Singh
5
自 MySQL 5.6 版本起,DATE 类型应该能够使用默认值 NOW() - AbcAeffchen
1
根据mysql 5.6文档:http://dev.mysql.com/doc/refman/5.6/en/data-type-defaults.html,您可以使用CURRENT_TIMESTAMP()作为默认值。 - blacktie24
1
我该如何实现 CURRENT_TIMESTAMP + 1 DAY? - Ilker Baltaci
13个回答

271

从MySQL 5.6.5开始,您可以使用具有动态默认值的DATETIME类型:

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

甚至可以将两个规则结合起来:

modification_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

参考:
http://dev.mysql.com/doc/refman/5.7/en/timestamp-initialization.html
http://optimize-this.blogspot.com/2012/04/datetime-default-now-finally-available.html

在5.6.5之前,您需要使用TIMESTAMP数据类型,该类型会在记录修改时自动更新。然而,每个表中只能存在一个自动更新的TIMESTAMP字段。

CREATE TABLE mytable (
  mydate TIMESTAMP
)

参见:http://dev.mysql.com/doc/refman/5.1/en/create-table.html

如果您想要阻止 MySQL 在 UPDATE 操作时更新时间戳的值(仅在 INSERT 操作时更新),您可以将定义更改为:

CREATE TABLE mytable (
  mydate TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)

81
我不想使用时间戳。 - Ibrahim Azhar Armar
9
手册明确指出:"例如,这意味着您不能将日期列的默认值设置为诸如NOW()或CURRENT_DATE之类的函数值。" - Nicola Cossu
21
在存储生日等未来超过30年的信息时,通常会优先选择使用DATETIME类型,因为它可以存储的范围更广,从 '1000-01-01 00:00:00' 至 '9999-12-31 23:59:59',而相比之下,TIMESTAMPS只能存储从协调世界时(UTC)'1970-01-01 00:00:01' 至 '2038-01-19 03:14:07' 的时间戳。 - user17753
2
只能有一个带有DEFAULT CURRENT_TIMESTAMP的TIMESTAMP列。因此,如果您希望使用2个列,例如“date_created”和“last_edit”,那么这种解决方案是行不通的。 - RouR
5
从MySQL 5.6开始,您不再仅限于使用“时间戳”来实现此行为。 - Dan Esparza
显示剩余6条评论

71

我使用触发器来解决新插入数据时将日期时间字段设置为NOW()的问题:

CREATE TRIGGER `triggername` BEFORE INSERT ON  `tablename` 
FOR EACH ROW 
SET NEW.datetimefield = NOW()

它也应该适用于更新操作

Johan 和 Leonardo 的答案涉及将其转换为时间戳字段。虽然这对于问题中提出的用例(存储 RegisterDate 和 LastVisitDate)可能是可以接受的,但它并不是一个通用解决方案。请参见 datetime vs timestamp 问题。


4
这应该是被采纳的答案,但你应该编辑一下,让它明显表明它只适用于日期时间字段。原始发布者想知道如何解决日期时间字段的问题,如果你真正学习过这两种数据类型之间的区别,那么使用时间戳是一个愚蠢的变通办法。 - phpguru

47

我的解决方案

ALTER TABLE `table_name` MODIFY COLUMN `column_name` TIMESTAMP NOT
NULL DEFAULT CURRENT_TIMESTAMP;

这个函数可行,我建议每个人都使用SQLYog或类似的工具,它可以让你在一个简单的界面上完成这些操作。 - Immutable Brick
31
这仍然是“TIMESTAMP”列的解决方案。没有人要求“TIMESTAMP”... - Petr Peller
2
是的,这不是问题的答案。TIMESTAMP是一种与DATETIME不同的字段类型。 - John Hunt
@Leonardo 我该如何仅显示日期? - 151291

14

终于找到了!!!


对于所有曾经尝试在 MySQL 中设置默认 DATETIME 值 而感到失落的人,我知道你们的感受。所以这就是解决方法:

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

仔细观察,我没有在0周围添加单引号/双引号。


重要更新:

这个答案是很久以前发布的。当时,在我的(可能是最新的)MySQL安装上运行良好,我觉得可以分享一下。在决定现在使用此解决方案之前,请先阅读下面的评论。


17
取决于期望...
  • 这个解决方案允许你拥有非空字段,因为提供了默认值。
  • 这个解决方案不会将字段设置为 NOW()。
- CodeReaper
10
这不回答原始问题,答案应该清楚地说明这一点。 - Matt Browne
2
请注意,传统的SQL模式包括NO_ZERO_DATE,因此在这种情况下上述内容将无法工作。 - Móż
这个答案不正确。在单引号中的“0000-00-00 00:00:00”是非空日期时间字段的“零”等效值,应尽可能避免使用,因为有很多原因。如果您真的不想使用时间戳,请使用触发器自动将日期时间更新为NOW()。 - phpguru
1
这个解决方案将会有一些API出现“天哪,是零日期!这是多么的异端邪说啊!我们无法将'this'转换为java.lang.Date/System.DateTime!天哪!-崩溃-” 的情况。 - Felype
显示剩余4条评论

11

在mysql 5.6.5及更高版本中,您可以使用精确的日期时间并设置默认值。 然而有一个微妙的问题,就是需要将精度值传递到datetime和NOW()函数调用中。

这个例子有效:

    ALTER TABLE my_table MODIFY created datetime(6) NOT NULL DEFAULT NOW(6);

这个示例不起作用:

    ALTER TABLE my_table MODIFY created datetime(6) NOT NULL DEFAULT NOW();

3

准确地说是从5.6.5版本开始,因为我有5.6.22版本,但即使它是5.6版本,也无法正常工作。太糟糕了。 - Delphine

1
`ALTER TABLE  `table_name` CHANGE `column_name` 
    timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP 
    ON UPDATE CURRENT_TIMESTAMP

可以用来更新更新时间戳。

1
最好的方法是使用“DEFAULT 0”。 另一种方法:
    /************ 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();

0
ALTER TABLE table_name
  CHANGE COLUMN date_column_name date_column_name DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP;

终于,这对我有用!


0

这对我有用,使用MySQL:

ALTER TABLE `table_name` MODIFY `column_name` datetime NOT NULL DEFAULT NOW();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接