在MySQL 4.0中同时具有Created和Last Updated timestamp列


127

我有以下表模式;

CREATE TABLE `db1`.`sms_queue` (
  `Id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
  `Message` VARCHAR(160) NOT NULL DEFAULT 'Unknown Message Error',
  `CurrentState` VARCHAR(10) NOT NULL DEFAULT 'None',
  `Phone` VARCHAR(14) DEFAULT NULL,
  `Created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `LastUpdated` TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP,
  `TriesLeft` tinyint NOT NULL DEFAULT 3,
  PRIMARY KEY (`Id`)
)
ENGINE = InnoDB;

失败并显示以下错误:

ERROR 1293 (HY000): Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause.

我的问题是,我可以同时拥有这两个领域吗?还是我必须在每次交易期间手动设置LastUpdated字段?


嘿,@ Xenph Yan,您介意将“接受的”答案从当前的错误答案更改为正确的答案吗?这个被接受的错误答案使我损失了大约15分钟的时间来试图弄清正在发生的事情……
Bruno Reis

1
@BrunoReis完成,谢谢接送。
Xenph Yan

Answers:


128

MySQL 5.5文档中

表中的一个TIMESTAMP列可以将当前时间戳记作为初始化该列的默认值,作为自动更新值或同时作为两者。当前时间戳不能是一列的默认值,而另一列的自动更新值是不可能的。

MySQL 5.6.5中的更改

以前,每个表最多可以自动将TIMESTAMP列初始化或更新为当前日期和时间。此限制已解除。任何TIMESTAMP列定义都可以具有DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP子句的任意组合。此外,这些子句现在可以与DATETIME列定义一起使用。有关更多信息,请参见TIMESTAMP和DATETIME的自动初始化和更新。


情况已经改变(至少在MySQL 5.0中)。请参阅文档:dev.mysql.com/doc/refman/5.0/en/timestamp.html
SimonSimCity

反@SimonSimCity:5.0的文档说的和上面完全一样。
davemyron

5
@RobertGamble我认为更有趣的问题是,为什么他们没有提供一种通常需要/需要的功能。

22
对于MySQL来说,这似乎有些武断。谁能解释为什么会这样?
humble_coder

12
真的很老的评论,但是,它终于被改变了: Changes in MySQL 5.6.5 (2012-04-10, Milestone 8) Previously, at most one TIMESTAMP column per table could be automatically initialized or updated to the current date and time. This restriction has been lifted. Any TIMESTAMP column definition can have any combination of DEFAULT CURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP clauses. In addition, these clauses now can be used with DATETIME column definitions. For more information, see Automatic Initialization and Updating for TIMESTAMP and DATETIME.
Mauricio Vargas

83

拥有两个时间戳都有一个技巧,但是有一些限制。

您只能在一个表中使用其中一种定义。创建两个时间戳列,如下所示:

create table test_table( 
  id integer not null auto_increment primary key, 
  stamp_created timestamp default '0000-00-00 00:00:00', 
  stamp_updated timestamp default now() on update now() 
); 

请注意,在以下过程中必须同时输入null两列insert

mysql> insert into test_table(stamp_created, stamp_updated) values(null, null); 
Query OK, 1 row affected (0.06 sec)

mysql> select * from test_table; 
+----+---------------------+---------------------+ 
| id | stamp_created       | stamp_updated       |
+----+---------------------+---------------------+
|  2 | 2009-04-30 09:44:35 | 2009-04-30 09:44:35 |
+----+---------------------+---------------------+
2 rows in set (0.00 sec)  

mysql> update test_table set id = 3 where id = 2; 
Query OK, 1 row affected (0.05 sec) Rows matched: 1  Changed: 1  Warnings: 0  

mysql> select * from test_table;
+----+---------------------+---------------------+
| id | stamp_created       | stamp_updated       | 
+----+---------------------+---------------------+ 
|  3 | 2009-04-30 09:44:35 | 2009-04-30 09:46:59 | 
+----+---------------------+---------------------+ 
2 rows in set (0.00 sec)  

下面是从MySQL-文档描述该功能的链接:dev.mysql.com/doc/refman/5.0/en/timestamp.html
SimonSimCity

6
手动输入时,第一个代码框对我来说非常合适。谢谢!我希望我有足够的“业力”来支持这个答案,因为它节省了我的培根。mmmmm节省了培根。
amatusko 2012年

您需要确保将stamp_created 其也设置为NOT NULL。MySQL将自动用当前时间戳替换NULL。
Valentin Despa

您为什么不也将stamp_created字段设置为:stamp_created timestamp default now()而不是使用“零”值?
塞巴斯蒂安·斯科尔

28

您可以同时拥有它们,只需在创建的字段上取消“ CURRENT_TIMESTAMP”标志即可。每当您在表中创建新记录时,只需使用“ NOW()”作为值。

要么。

相反,删除“ ON UPDATE CURRENT_TIMESTAMP”标志并发送该字段的NOW()。这样实际上更有意义。


2
这是唯一的方法吗?我不能让数据库照看所有这些细节吗?
Xenph Yan

2
根据MySql手册,CURRENT_TIMESTAMP是NOW()的同义词,所以我认为这不起作用。
tvanfosson

我确定可以,只是CURRENT_TIMESTAMP是仅保留一个字段的标志。无论哪种方式,如果都在其中具有该标志,则无论添加记录时该字段具有什么值,它始终是当前时间戳,因此是名称。
斯蒂芬·沃尔彻

1
@tvanfosson:在查询中使用“ NOW()”将当前时间传递给数据库。该值实际上取决于语言,引擎以及可能不知道的其他一百多种东西。我所指的标志将其设置为在创建记录时将时间添加到该字段。
斯蒂芬·沃尔彻

2
我采用insert NOW()方式,主要是因为其他代码可能会触及这些表,而且我不相信人们会正确地更新它们。:)
Xenph Yan

26

如果您决定让MySQL处理时间戳的更新,则可以设置触发器以在插入时更新字段。

CREATE TRIGGER <trigger_name> BEFORE INSERT ON <table_name> FOR EACH ROW SET NEW.<timestamp_field> = CURRENT_TIMESTAMP;

MySQL参考:http//dev.mysql.com/doc/refman/5.0/en/triggers.html


很好,这就是我想要的。我不想依赖于在查询中添加NOW()的人!
Bot

实际上,最好在插入后再执行,然后设置NEW。<timestamp_field> = new。<timestamp_field实际上必须具有默认的current_timestamp>,这样两个字段都是一致的
KacieHouser 2011年

@KacieHouser触发后不允许更新新行
Thomas

23

这是使用触发器如何自动且灵活的createDate / lastModified字段的方法:

首先像这样定义它们:

CREATE TABLE `entity` (
  `entityid` int(11) NOT NULL AUTO_INCREMENT,
  `createDate` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `lastModified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `name` varchar(255) DEFAULT NULL,
  `comment` text,
  PRIMARY KEY (`entityid`),
)

然后添加以下触发器:

DELIMITER ;;
CREATE trigger entityinsert BEFORE INSERT ON entity FOR EACH ROW BEGIN SET NEW.createDate=IF(ISNULL(NEW.createDate) OR NEW.createDate='0000-00-00 00:00:00', CURRENT_TIMESTAMP, IF(NEW.createDate<CURRENT_TIMESTAMP, NEW.createDate, CURRENT_TIMESTAMP));SET NEW.lastModified=NEW.createDate; END;;
DELIMITER ;
CREATE trigger entityupdate BEFORE UPDATE ON entity FOR EACH ROW SET NEW.lastModified=IF(NEW.lastModified<OLD.lastModified, OLD.lastModified, CURRENT_TIMESTAMP);
  • 如果插入时未指定createDate或lastModified,则它们将相等并设置为当前时间戳。
  • 如果您在未指定createDate或lastModified的情况下更新它们,则lastModified将设置为当前时间戳。

但是,这是一个很好的部分:

  • 如果您插入,则可以指定一个比当前时间戳更早createDate,从而允许从较早的时间进行导入(lastModified等于createDate)。
  • 如果您进行更新,则可以指定一个比以前的值还早lastModified('0000-00-00 00:00:00'可以正常工作),如果您要进行外观更改,则可以更新条目(修正注释中的错字) ),您想保留旧的lastModified日期。这不会修改lastModified日期。

21

从MySQL 5.6开始,它很容易...尝试一下:

create table tweet ( 
    id integer not null auto_increment primary key, 
    stamp_created timestamp default now(), 
    stamp_updated timestamp default now() on update now(),
    message varchar(163)
)

可能是很棒的解决方案我正在搜索的内容没有触发就创建和更新时间问题
Matinict

我不敢相信这个小小的麻烦花了很长时间才得以解决。我什至没有意识到他们已经解决了这个问题,现在是2018年...谢谢。
桑德斯18-3-16

4

这个问题在MySQL 5.6中似乎已经解决。在MySQL 5.5之前,我已经注意到了这一点。这是一个示例代码:

DROP TABLE IF EXISTS `provider_org_group` ;
CREATE TABLE IF NOT EXISTS `provider_org_group` (
  `id` INT NOT NULL,
  `name` VARCHAR(100) NOT NULL,
  `type` VARCHAR(100) NULL,
  `inserted` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `insert_src_ver_id` INT NULL,
  `updated` TIMESTAMP NULL ON UPDATE CURRENT_TIMESTAMP,
  `update_src_ver_id` INT NULL,
  `version` INT NULL,
  PRIMARY KEY (`id`),
  UNIQUE INDEX `id_UNIQUE` (`id` ASC),
  UNIQUE INDEX `name_UNIQUE` (`name` ASC))
ENGINE = InnoDB;

在MySQL 5.5上运行可以得到:

ERROR 1293 (HY000): Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause

在MySQL 5.6上运行

0 row(s) affected   0.093 sec


2

对于mysql 5.7.21,我使用以下命令并可以正常工作:

CREATE TABLE Postsmodified_at时间戳NULL NOT NULL DEFAULT CURRENT_TIMESTAMP在UPDATE CURRENT_TIMESTAMP上, created_at时间戳NOT NULL DEFAULT CURRENT_TIMESTAMP)


1

我认为这是对stamp_created和stamp_updated更好的查询

CREATE TABLE test_table( 
    id integer not null auto_increment primary key, 
    stamp_created TIMESTAMP DEFAULT now(), 
    stamp_updated TIMESTAMP DEFAULT '0000-00-00 00:00:00' ON UPDATE now() 
); 

因为记录创建时,stamp_created应填写now()stamp_updated应填写'0000-00-00 00:00:00'


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.