在写这篇文章之前。明白我的MySQL版本号。

mysql> SELECT VERSION();
+------------+
| VERSION() |
+------------+
| 5.5.29-log |
+------------+
1 row in set (0.00 sec)

如今有这种需求,一张表中有一个字段created_at记录创建该条记录的时间戳,另一个字段updated_at记录更新该条记录的时间戳。
我们尝试下面几个语句。

第一个,測试通过。

CREATE TABLE temp
(
id INT(11) PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(10),
updated_at timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

第二个,測试不通过。报ERROR 1293 (HY000)错误。(完整错误信息:ERROR 1293 (HY000): Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause)

CREATE TABLE temp
(
id INT(11) PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(10),
created_at timestamp NULL DEFAULT CURRENT_TIMESTAMP,
updated_at timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

MySQL 5.5.29中有这种奇葩限制,不明白为什么。既然有这种限制。那么仅仅有绕道而行。如今尝试给出例如以下几种解决的方法。

第一种,created_at使用DEFAULT CURRENT_TIMESTAMP或者DEFAULT now(),updated_at使用触发器。
详细解决方法例如以下:
1.temp表结构例如以下:

CREATE TABLE temp
(
id INT(11) PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(10),
created_at timestamp NULL DEFAULT CURRENT_TIMESTAMP,
updated_at timestamp NULL
);

2.插入測试数据:

mysql> INSERT INTO temp(name,created_at,updated_at) VALUES('robin',now(),now());
Query OK, 1 row affected (0.03 sec) mysql> INSERT INTO temp(name,created_at,updated_at) VALUES('wentasy',now(),now());
Query OK, 1 row affected (0.01 sec) mysql> SELECT * FROM temp;
+----+---------+---------------------+---------------------+
| id | name | created_at | updated_at |
+----+---------+---------------------+---------------------+
| 1 | robin | 2014-09-01 14:00:39 | 2014-09-01 14:00:39 |
| 2 | wentasy | 2014-09-01 14:01:11 | 2014-09-01 14:01:11 |
+----+---------+---------------------+---------------------+
2 rows in set (0.00 sec)

3.在temp上创建触发器,实现更新时记录更新时间;

delimiter |
DROP TRIGGER IF EXISTS tri_temp_updated_at;
CREATE TRIGGER tri_temp_updated_at BEFORE UPDATE ON temp
FOR EACH ROW
BEGIN
SET NEW.updated_at = now();
END;
|
delimiter ;

4.測试。

mysql> UPDATE temp SET name='robinwen' WHERE id=1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0 #能够看到已经记录了第一条数据的更新时间
mysql> SELECT * FROM temp;
+----+----------+---------------------+---------------------+
| id | name | created_at | updated_at |
+----+----------+---------------------+---------------------+
| 1 | robinwen | 2014-09-01 14:00:39 | 2014-09-01 14:03:05 |
| 2 | wentasy | 2014-09-01 14:01:11 | 2014-09-01 14:01:11 |
+----+----------+---------------------+---------------------+
2 rows in set (0.00 sec)

另外一种,created_at使用触发器。updated_at使用DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP或者DEFAULT now() ON UPDATE now()。

详细解决方法例如以下:
1.temp表结构例如以下:

CREATE TABLE temp
(
id INT(11) PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(10),
created_at timestamp NULL,
updated_at timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

2.在temp上创建触发器。实现插入数据记录创建时间。

delimiter |
DROP TRIGGER IF EXISTS tri_temp_created_at;
CREATE TRIGGER tri_temp_created_at BEFORE INSERT ON temp
FOR EACH ROW
BEGIN
IF new.created_at IS NULL
THEN
SET new.created_at=now();
END IF;
END;
|
delimiter ;

3.插入測试数据:

mysql> INSERT INTO temp(name,created_at,updated_at) VALUES('robin',now(),now());
Query OK, 1 row affected (0.01 sec) mysql> INSERT INTO temp(name,created_at,updated_at) VALUES('wentasy',now(),now());
Query OK, 1 row affected (0.01 sec) mysql> SELECT * FROM temp;
+----+---------+---------------------+---------------------+
| id | name | created_at | updated_at |
+----+---------+---------------------+---------------------+
| 1 | robin | 2014-09-01 14:08:36 | 2014-09-01 14:08:36 |
| 2 | wentasy | 2014-09-01 14:08:44 | 2014-09-01 14:08:44 |
+----+---------+---------------------+---------------------+
2 rows in set (0.00 sec)

4.測试。

mysql> UPDATE temp SET name='robinwen' WHERE id=1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0 #能够看到已经记录了第一条数据的更新时间
mysql> SELECT * FROM temp;
+----+----------+---------------------+---------------------+
| id | name | created_at | updated_at |
+----+----------+---------------------+---------------------+
| 1 | robinwen | 2014-09-01 14:08:36 | 2014-09-01 14:09:09 |
| 2 | wentasy | 2014-09-01 14:08:44 | 2014-09-01 14:08:44 |
+----+----------+---------------------+---------------------+
2 rows in set (0.00 sec)

第三种,created_at指定timestamp DEFAULT '0000-00-00 00:00:00',updated_at指定DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP或者timestamp DEFAULT now() ON UPDATE now()。
详细解决方法例如以下:
1.temp表结构例如以下:

CREATE TABLE temp
(
id INT(11) PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(10),
created_at timestamp NULL DEFAULT '0000-00-00 00:00:00',
updated_at timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

2.插入測试数据:

mysql> INSERT INTO temp(name,created_at,updated_at) VALUES('robin',now(),now());
Query OK, 1 row affected (0.01 sec) mysql> INSERT INTO temp(name,created_at,updated_at) VALUES('wentasy',now(),now());
Query OK, 1 row affected (0.01 sec) mysql> SELECT * FROM temp;
+----+---------+---------------------+---------------------+
| id | name | created_at | updated_at |
+----+---------+---------------------+---------------------+
| 1 | robin | 2014-09-01 14:10:43 | 2014-09-01 14:10:43 |
| 2 | wentasy | 2014-09-01 14:10:57 | 2014-09-01 14:10:57 |
+----+---------+---------------------+---------------------+
2 rows in set (0.00 sec)

3.測试。

mysql> UPDATE temp SET name='robinwen' WHERE id=1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0 #能够看到已经记录了第一条数据的更新时间
mysql> SELECT * FROM temp;
+----+----------+---------------------+---------------------+
| id | name | created_at | updated_at |
+----+----------+---------------------+---------------------+
| 1 | robinwen | 2014-09-01 14:10:43 | 2014-09-01 14:11:24 |
| 2 | wentasy | 2014-09-01 14:10:57 | 2014-09-01 14:10:57 |
+----+----------+---------------------+---------------------+
2 rows in set (0.00 sec)

第四种,更换MySQL版本号,MySQL 5.6已经去除了此限制。

我们能够看下MySQL 5.5和5.6帮助文档对于这个问题的解释。

From the MySQL 5.5 documentation:

One TIMESTAMP column in a table can have the current timestamp as the default value for initializing the column, as the auto-update value, or both. It is not possible to have the current timestamp be the default value for one column and the auto-update value for another column.

Changes in MySQL 5.6.5:

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.

我们确定下MySQL的版本号。

mysql> SELECT VERSION();
+---------------------------------------+
| VERSION() |
+---------------------------------------+
| 5.6.20-enterprise-commercial-advanced |
+---------------------------------------+
1 row in set (0.00 sec)

我们把文首測试不通过的SQL语句在MySQL 5.6下运行。能够看到没有不论什么错误。

CREATE TABLE temp
(
id INT(11) PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(10),
created_at timestamp NULL DEFAULT CURRENT_TIMESTAMP,
updated_at timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
Query OK, 0 rows affected (0.28 sec)

接着我们插入測试语句,并作測试。

mysql> INSERT INTO temp(name) VALUES('robin');
Query OK, 1 row affected (0.07 sec) mysql> INSERT INTO temp(name) VALUES('wentasy');
Query OK, 1 row affected (0.00 sec) mysql> SELECT * FROM temp;
+----+---------+---------------------+---------------------+
| id | name | created_at | updated_at |
+----+---------+---------------------+---------------------+
| 1 | robin | 2014-09-01 15:05:57 | 2014-09-01 15:05:57 |
| 2 | wentasy | 2014-09-01 15:06:02 | 2014-09-01 15:06:02 |
+----+---------+---------------------+---------------------+
2 rows in set (0.01 sec) mysql> UPDATE temp SET name='robinwen' WHERE id=1;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0 #能够看到已经记录了第一条数据的更新时间
mysql> SELECT * FROM temp;
+----+----------+---------------------+---------------------+
| id | name | created_at | updated_at |
+----+----------+---------------------+---------------------+
| 1 | robinwen | 2014-09-01 15:05:57 | 2014-09-01 15:06:45 |
| 2 | wentasy | 2014-09-01 15:06:02 | 2014-09-01 15:06:02 |
+----+----------+---------------------+---------------------+
2 rows in set (0.00 sec)

总结
本文介绍的方法归根结底。就两条,一是建表语句指定默认值和更新动作。二是使用触发器插入默认值和更新时间。面对当前无法更改的事实,仅仅能採取折中的办法或者牺牲很多其它来弥补。另一条值得注意的是,遇到问题多想想不同的解决的方法。尽可能地列出全部可能或者可行的方案。这样一来让自己学到很多其它,二来能够锻炼思维的广度,三来多种方案能够弥补某种方案在特定环境下不可行的不足。

Good Luck!

Robin

2014年9月1日

MySQL中同一时候存在创建和上次更新时间戳字段解决方法浅析的更多相关文章

  1. MySQL中同时存在创建和更新时间戳字段解决方法浅析

    MySQL中同时存在创建和更新时间戳字段解决方法浅析 明确我的MySQL版本.mysql> SELECT VERSION();+------------+| VERSION() |+------ ...

  2. MySQL there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause同时创建多个更新当前时间戳字段 解决方法

    问题重现 在写这篇文章之前,明确我的MySQL版本,MariaDB 或者你使用 MySQL 8 也会出现如下问题 MySQL 版本 现在有这样的需求,一张表中有一个字段created_at记录创建该条 ...

  3. mysql创建外链失败1005错误解决方法

    mysql创建外链失败1005错误解决方法 错误号:1005错误信息:Can't create table 'webDB.#sql-397_61df' (errno: 150)解决方法 错误原因有四: ...

  4. MySQL 中的数据库名称、数据表名称、字段名称

    如何查询Oracle,Sql Server,MySQL 中的数据库名称.数据表名称.字段名称 分类: Database2012-09-24 22:16 7034人阅读 评论(0) 收藏 举报 数据库s ...

  5. 优化MySQL开启skip-name-resolve参数时显示“ignored in --skip-name-resolve mode.”Warning解决方法

    转自:http://blog.csdn.net/yiluoak_47/article/details/53381282 参数用途: skip-name-resolve #禁止MySQL对外部连接进行D ...

  6. rpm包安装过程中依赖问题“libc.so.6 is needed by XXX”解决方法

    rpm包安装过程中依赖问题"libc.so.6 is needed by XXX"解决方法 折腾了几天,终于搞定了CentOS上的Canon LBP2900打印机驱动.中间遇到了一 ...

  7. php 字符串中的\n换行符无效、不能换行的解决方法

    php 字符串中的\n换行符无效.不能换行的解决方法 程序的中的换行符\n会直接输出,无法正确换行,解决方法是把单引号改为双引号 aa

  8. 关于swift语言中导入OC三方类找不到头文件的解决方法

    首先我遇到的问题是这样的: 我之前封装的OC类,我导入现在的swift工程中,然后建立桥接文件,在Swift的控制器中可以找到这个OC写的东西. 但是问题来了,当你使用cocoapods导入的OC三方 ...

  9. easyui 中iframe嵌套页面,大弹窗自适应居中的解决方法。$('#win').window()

    easyui 中iframe嵌套页面,大弹窗自适应居中的解决方法.$('#win').window() 以下是左边栏和头部外层遮罩显示和隐藏方法 /*外层 遮罩显示*/ function wrapMa ...

随机推荐

  1. 五、Nginx多Server反向代理配置

    Nginx强大的正则表达式支持,可以使server_name的配置变得很灵活,如果你要做多用户博客,那么每个用户拥有自己的二级域名也就很容易实现了. server_name的匹配顺序 Nginx中的s ...

  2. Java--CyclicBarrier使用简介

    CyclicBarrier介绍 (一)一 个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point).在涉及一组固定大小的线程的程序中,这些线程必须不时 ...

  3. 配置Jenkins的slave节点的详细步骤适合windows等其他平台(转)

    @  新建一个slave节点在Jenkins服务器上 1,进入Jenkins的主界面,进入“Manage Jenkins” 页面: 2,点击如下图中的“Manage  Nodes”: 3,进入页面后点 ...

  4. Ubuntu 14.04下安装GitLab指南

    摘要 GitLab 是一个用于仓库管理系统的开源项目.使用Git作为代码管理工具,并在此基础上搭建起来的web服务. 在GitLab的官方网站上面对Ubuntu的支持也是很好的,有比较详尽的安装指南. ...

  5. css sprites 图片精灵自动生成 插件

    grunt-spritesmith https://www.npmjs.com/package/grunt-spritesmith

  6. C#面向对象2 静态类、静态成员的理解

    理解:静态成员属于类所有,为各个类的实例所公用,与实例无关,需要全局共享的属性或者方法定义成静态的 C#静态成员:  1.静态成员属于类所有,故用类名调用,非静态成员属于类的实例所有,用实例名调用  ...

  7. SSH2三大框架整合警告

    *********************************************************************** * WARNING!!! * * * * >> ...

  8. 终于实现samba可写不可删除

    通过szxsztszk的提示 今天终于实现了linux可写不可删除的要求. 同时运用了POSIX ACL 我们公司的要求是这样的[color=Red](我只做出我公司要求的步骤,不同的要求,稍加改正即 ...

  9. Sting和StringBuffer的区别

    java.lang.String代表不可变序列: s1 = "hello"; s2 = "world"; s1 = s1 + s2; 内存分配情况是s1有块内存 ...

  10. [置顶] Guava学习之Lists

    Lists类主要提供了对List类的子类构造以及操作的静态方法.在Lists类中支持构造ArrayList.LinkedList以及newCopyOnWriteArrayList对象的方法.其中提供了 ...