为什么DEFAULT子句中只有一个TIMESTAMP列和CURRENT_TIMESTAMP?

时间:2010-12-20 12:19:44

标签: mysql timestamp mysql-error-1293

为什么在DEFAULT或ON UPDATE子句中只能有一个带CURRENT_TIMESTAMP的TIMESTAMP列?

CREATE TABLE `foo` (
  `ProductID` INT(10) UNSIGNED NOT NULL,
  `AddedDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `UpdatedDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=INNODB;

导致的错误:

  

错误代码:1293

     

表定义不正确;有可以   只有一个TIMESTAMP列   DEFAULT或ON中的CURRENT_TIMESTAMP   UPDATE子句

9 个答案:

答案 0 :(得分:163)

这个限制只是由于历史代码遗留原因,在最近的MySQL版本中被取消了:

  

MySQL 5.6.5(2012-04-10,Milestone 8)中的变化

     

以前,每个表最多只能有一个TIMESTAMP列   自动初始化或更新到当前日期和时间。   这一限制已被取消。任何TIMESTAMP列定义都可以   具有DEFAULT CURRENT_TIMESTAMP和ON UPDATE的任意组合   CURRENT_TIMESTAMP子句。此外,现在可以使用这些条款   使用DATETIME列定义。有关更多信息,请参阅自动   TIMESTAMP和DATETIME的初始化和更新。

http://dev.mysql.com/doc/relnotes/mysql/5.6/en/news-5-6-5.html

答案 1 :(得分:39)

我很久以前也想知道。我在历史记录中搜索了一下,我认为这篇文章:http://lists.mysql.com/internals/34919代表MySQL的半官方立场(在Oracle干预之前;))

简而言之:

  

这种限制仅源于   目前此功能的方式   在服务器和那里实现   没有其他原因   存在。

所以他们的解释是“因为它是这样实现的”。听起来不是很科学。我猜这一切都来自一些旧代码。这在上面的主题中建议:“仅在第一个时间戳字段被自动设置/更新时结转”。

干杯!

答案 2 :(得分:34)

我们可以为时间戳指定默认值以避免此问题。

这篇文章给出了详细的解决方法: http://gusiev.com/2009/04/update-and-create-timestamps-with-mysql/

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

请注意,在“insert”期间,必须在两列中输入空值:

mysql> insert into test_table(stamp_created, stamp_updated) values(null, null); 
Query OK, 1 row affected (0.06 sec)
mysql> select * from t5; 
+----+---------------------+---------------------+ 
| 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) 

答案 3 :(得分:16)

确实是一个实现错误。

MySQL中的原生方法是自己更新创建日期(如果需要),让MySQL担心时间戳 update date ? update date : creation date,如下所示:

CREATE TABLE tracked_data( 
  `data` TEXT,
  `timestamp`   TIMESTAMP,
  `creation_date` TIMESTAMP                                   
) ENGINE=INNODB; 

创建时插入NULL:

INSERT INTO tracked_data(`data`,`creation_date`) VALUES ('creation..',NULL);

默认情况下,时间戳的NULL值会被固定为CURRENT_TIMESTAMP。

在MySQL中,如果没有给出属性,则表的第一个TIMESTAMP列将同时获得DEFAULT CURRENT_TIMESTAMPON UPDATE CURRENT_TIMESTAMP属性。 这就是具有属性的TIMESTAMP列必须首先出现的原因,或者您得到此线程中描述的错误。

答案 4 :(得分:13)

  1. 将列的数据类型更改为datetime
  2. 设置触发器
  3. 如:

    DROP TRIGGER IF EXISTS `update_tablename_trigger`;
    DELIMITER //
    CREATE TRIGGER `update_tablename_trigger` BEFORE UPDATE ON `tablename`
     FOR EACH ROW SET NEW.`column_name` = NOW()
    //
    DELIMITER ;
    

答案 5 :(得分:1)

您可以将它放在UpdatedDate字段上,并且只有在AddedDate为空时才有一个触发器使用UpdatedDate值更新AddedDate字段。

答案 6 :(得分:1)

结合各种答案:

在MySQL 5.5中,DEFAULT CURRENT_TIMESTAMPON UPDATE CURRENT_TIMESTAMP无法添加到DATETIME,而只能添加到TIMESTAMP

<强>规则:

1)每个表最多一个TIMESTAMP列可以自动(或手动[我的添加])初始化或更新到当前日期和时间。 (MySQL Docs)。

因此TIMESTAMPCURRENT_TIMESTAMP条款中只有一个DEFAULT可以ON UPDATE

2)第一个NOT NULL TIMESTAMP列没有明确的DEFAULT值,如created_date timestamp default '0000-00-00 00:00:00',将隐含地赋予DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,因此后续TIMESTAMP无法在CURRENT_TIMESTAMPDEFAULT子句

上为ON UPDATE添加列
CREATE TABLE `address` (
  `id` int(9) NOT NULL AUTO_INCREMENT,
  `village` int(11) DEFAULT NULL,
    `created_date` timestamp default '0000-00-00 00:00:00', 

    -- Since explicit DEFAULT value that is not CURRENT_TIMESTAMP is assigned for a NOT NULL column, 
    -- implicit DEFAULT CURRENT_TIMESTAMP is avoided.
    -- So it allows us to set ON UPDATE CURRENT_TIMESTAMP on 'updated_date' column.
    -- How does setting DEFAULT to '0000-00-00 00:00:00' instead of CURRENT_TIMESTAMP help? 
    -- It is just a temporary value.
    -- On INSERT of explicit NULL into the column inserts current timestamp.

-- `created_date` timestamp not null default '0000-00-00 00:00:00', // same as above

-- `created_date` timestamp null default '0000-00-00 00:00:00', 
-- inserting 'null' explicitly in INSERT statement inserts null (Ignoring the column inserts the default value)! 
-- Remember we need current timestamp on insert of 'null'. So this won't work. 

-- `created_date` timestamp null , // always inserts null. Equally useless as above. 

-- `created_date` timestamp default 0, // alternative to '0000-00-00 00:00:00'

-- `created_date` timestamp, 
-- first 'not null' timestamp column without 'default' value. 
-- So implicitly adds DEFAULT CURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP. 
-- Hence cannot add 'ON UPDATE CURRENT_TIMESTAMP' on 'updated_date' column.


   `updated_date` timestamp null on update current_timestamp,

  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=132 DEFAULT CHARSET=utf8;
INSERT INTO address (village,created_date) VALUES (100,null);
mysql> select * from address;
+-----+---------+---------------------+--------------+
| id  | village | created_date        | updated_date |
+-----+---------+---------------------+--------------+
| 132 |     100 | 2017-02-18 04:04:00 | NULL         |
+-----+---------+---------------------+--------------+
1 row in set (0.00 sec)
UPDATE address SET village=101 WHERE village=100;
mysql> select * from address;
+-----+---------+---------------------+---------------------+
| id  | village | created_date        | updated_date        |
+-----+---------+---------------------+---------------------+
| 132 |     101 | 2017-02-18 04:04:00 | 2017-02-18 04:06:14 |
+-----+---------+---------------------+---------------------+
1 row in set (0.00 sec)

其他选项(但updated_date是第一栏):

CREATE TABLE `address` (
  `id` int(9) NOT NULL AUTO_INCREMENT,
  `village` int(11) DEFAULT NULL,
  `updated_date` timestamp null on update current_timestamp,
  `created_date` timestamp not null , 
  -- implicit default is '0000-00-00 00:00:00' from 2nd timestamp onwards

  -- `created_date` timestamp not null default '0000-00-00 00:00:00'
  -- `created_date` timestamp
  -- `created_date` timestamp default '0000-00-00 00:00:00'
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=132 DEFAULT CHARSET=utf8;

答案 7 :(得分:0)

试试这个:

CREATE TABLE `test_table` (
`id` INT( 10 ) NOT NULL,
`created_at` TIMESTAMP NOT NULL DEFAULT 0,
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE = INNODB;

答案 8 :(得分:0)

这是MYSQL 5.5版本的限制。您需要将版本更新为5.6。

Error

我在MYSQL中添加表

时遇到此错误
  

表定义不正确;只能有一个TIMESTAMP列   在DEFAULT或ON UPDATE子句中使用CURRENT_TIMESTAMP我的新MYSQL

表看起来像这样。

  

create table table_name(col1 int(5)auto_increment primary key,col2   varchar(300),col3 varchar(500),col4 int(3),col5 tinyint(2),   col6 timestamp默认current_timestamp,col7时间戳默认值   更新current_timestamp上的current_timestamp,col8 tinyint(1)   默认0,col9 tinyint(1)默认1);

经过一段时间阅读不同MYSQL版本和一些谷歌搜索的变化。我发现在MYSQL 5.6版本中有一些更改。

本文将帮助您解决此问题。 http://www.oyewiki.com/MYSQL/Incorrect-table-definition-there-can-be-only-one-timestamp-column