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


897

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

在SQL Server中为getdate()。MySQL的等效项是什么?如果这是一个因素,我正在使用MySQL5.x。


4
我在mysql表中使用CURRENT_TIMESTAMP(不在查询中),也许这也可能有帮助。
鲁宾2012年

15
现在,此功能已添加到MySQL 5.6.5中。希望这对某人有帮助。optimize-this.blogspot.co.uk/2012/04/...
GhostInTheSecureShell

@GhostInTheSecureShell的任务是至少在Debian上安装它,但这绝对是一个了不起的功能。我认为最终所有这些“两个CURRENT_TIMESTAMP”问题都将得到缓解!
马克·迪米洛

它是now()函数,否则您可以在列级别使用默认设置。
Anshul Sharma

Answers:


862

重要编辑: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>

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


400
重要的是要注意datetime的范围是1000-9999,但是timestamp的范围只有1970-2038。如果您的系统必须存储出生日期,或者您必须处理类似30年抵押的付款计划之类的问题,那么这可能是个问题。dev.mysql.com/doc/refman/5.0/en/datetime.html
Kip

13
时间戳也要小心,因为它会神奇地自动更新...请参阅下一个答案stackoverflow.com/a/1483959/233906
Cerber

6
可能的,从5.6.5版本,请参见下面古斯塔夫的答案(我知道你的答案被张贴在MySQL的仍然是5.0!)
E2-E4

4
@Kip,您好,是否可以为DATE列设置默认值?(不是datetime专栏)。
萨吉布·阿查里亚

ti对于DATE列似乎不太可能:您必须使用DATETIME数据类型
Fabio Napodano

598

在版本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


3
“ menu_creation_time”的默认值无效
Fernando Trindade

2
@FernandoTrindade您需要MySQL 5.6.5或更高版本。您可以在这里看到它的工作方式:sqlfiddle.com/#
Gustav Bertram

1
@GustavBertram,我使用的是5.6.22版,但仍然出现如下错误:CREATE TABLE tbl(InsertDate DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,UpdateDate TIMESTAMP NULL UPDATE CURRENT_TIMESTAMP(6)); 错误代码:1294。“ UpdateDate”列的无效的ON UPDATE子句
Manish Sapkal,2014年

@ManishSapkal您使用的是TIMESTAMP,而不是DATETIME。另外,请勿将其设为NULL。
古斯塔夫·贝特拉姆

1
我认为“更新”语法是错误的。根据dev.mysql.com/doc/refman/5.6/en/timestamp-initialization.html的说明,应该是dt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
Dan Bough

148

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

也就是说,您可以通过创建一个Trigger来实现。

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

希望对您有所帮助。


21
在每个行集的foo上插入foo之前创建Trigger trigger_foo_SetCreatedAt。newed.at = UTC_TIMESTAMP();
kgriffs 2010年

5
使用时间戳可能比触发将来的健全性(维护)更好。尽管这是一个解决方案,但对于触发器而言,用例太琐碎了。
getWeberForStackExchange 2011年

8
您可能只想设置默认值IF NEW.created_at IS NOT NULL
Petr Peller

132

对我而言,触发方法效果最好,但我发现该方法存在障碍。考虑以下基本触发器,以便在插入时将日期字段设置为当前时间:

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());

这提供了两全其美的方法:您可以为date列提供一个值,它将使用,否则将默认为当前时间。相对于表定义中的DEFAULT GETDATE()这样的干净内容,它仍然是贫民窟,但我们之间的距离越来越近了!


5
+1用于在插入时覆盖显式用户值来确认警告。
Kip

2
我个人认为这是最好的方法。TIMESTAMP确实确实有奇怪的行为,我永远也不会写有2038年限制的代码。
埃里克(Eric)2012年

没关系,我知道了。忘记将字段设置为允许NULL。没有警告了。
卡吉2012年

触发器是邪恶的!仅在没有其他方法可以使用时才使用它们。比使用触发器更好地升级到5.6.x id。
ksymeon 2015年

4
在MySQL 5.5中,IFNULL在DATETIME上不起作用。使用以上触发器,dateAdded将显示所有“ 0000-00-00 00:00:00”。使用这个方法可以达到目的:`如果NEW.dateAdded = 0,则逐行,然后设置NEW.dateAdded = NOW();。END IF;`
Kenney 2015年

28

我可以使用表上有两个datetime字段的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的一些新手可能不知道...

Yikes,对缺少换行符感到抱歉。使用分号标记每行的结尾。

24

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

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;

18

对于所有为在MySQL中设置默认DATETIME值而灰心的人,我确切地知道您的感觉/感觉。所以这里是:

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

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

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


8
它不会插入当前时间。它将插入'0000-00-00 00:00:00'。
Pit Digger)

8
我没有说它设置了当前时间。许多人试图/正在尝试设置默认的零值,但它根本不起作用。我们需要消除引号。由于这一发现引起了很多时间和沮丧,我想与社区分享。像您这样的人要对用户失去与他人共享有用信息的兴趣负责。我严重看不到获得-1的任何理由!随你。
Augiwan 2011年

3
使用DATETIME NOT NULL可以实现相同的目的。
布伦丹·伯德

示例sql命令中还有一个`字符,我不能将其删除,因为它仅是一个字符的编辑。
夸普卡'16

您的代码对我不起作用,这是起作用的东西ALTER TABLE zones MODIFY created datetime NOT NULL DEFAULT 0;
Smith,


14

如果您已经创建了表格,则可以使用

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

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 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文档中提到:

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

即使他们也说:

无效的DATE,DATETIME或TIMESTAMP值将转换为适当类型(“ 0000-00-00”或“ 0000-00-00 00:00:00”)的“零”值。


8

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


4
真正。我刚刚尝试使用它,但出现错误“错误代码:1067。默认值无效。”。那么答案是什么?;-)
Brian Boatright,

这是危害MySQL 5.5和5.6版本的最佳解决方案。对于5.5版,请预先确定的值,NOW()以后再用于插入。对于5.6版,只需将其设置NOW()为默认值即可。
Abel Callejo

8

对于所有使用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 '。它具有不同的属性,具体取决于MySQL版本和SQL服务器正在运行的模式。这些属性将在本节后面描述。

因此,这显然会在大约28年后破坏您的软件。

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


2
如果MySQL从现在开始20年进行了更新并且该限制已被删除怎么办?我不确定这是否可行,只是一个想法。
NessDan 2012年

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 ;

5

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

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

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


5
CHANGE也用于重命名该字段。第一列名称为“旧”,第二列名称为“新”。如果您不更改字段名称,它看起来是多余的。如果在美学上太令人讨厌,请尝试修改。
约翰·戈登

5

虽然您无法使用DATETIME默认定义来执行此操作,但是您可以像下面这样在您的插入语句中简单地加入一个select语句:

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

注意表周围没有引号。

对于MySQL 5.5


3

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


3

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

因此,您的查询应类似

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

谢谢。


2
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



0

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


0

例如,如果我有一个名为“ site”的表,且表的created_at和update_at列均为DATETIME,并且需要现在的默认值,则可以执行以下sql来实现此目的。

ALTER TABLE`site` CHANGE`created_at``created_at` TIMESTAMP不为空默认值CURRENT_TIMESTAMP;

ALTER TABLE`site` CHANGE`created_at``created_at` DATETIME NULL默认为NULL;

ALTER TABLE`site` CHANGE`updated_at``updated_at` TIMESTAMP不为空默认值CURRENT_TIMESTAMP;

ALTER TABLE`site`更改`updated_at``updated_at` DATETIME NULL默认为NULL;

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


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

与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;

-3

您可以解析默认时间戳。首先考虑一下您正在使用哪个字符集,例如,如果您采用utf8,则该字符集支持所有语言;如果您采用了Laten1,则此字符集仅支持英语。下一个setp(如果您正在任何项目下工作),您应该知道客户端时区并选择您为客户端时区。此步骤是必需的。


2
DateTime列不能具有默认值。它被记录为“功能”。并非所有开发人员都有权更改其字符编码。并且通常不可能将服务器设置为其客户端的时区,尤其是当客户端并非全部都属于单个时区时。
rlb.usa 2010年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.