在写这篇文章之前。明白我的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
BEGINSET 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
BEGINIF new.created_at IS NULLTHENSET 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 中constant_thinkphp提示Undefined class constant 'MYSQL_ATTR_INIT_COMMAND'报错的解决方法...

    在操作服务器的时候不知道怎么回事突然提示Undefined class constant 'MYSQL_ATTR_INIT_COMMAND',查找资料发现是php缺少pdo_mysql的扩展.:( U ...

  2. Eclipse Java Oxygen不能创建动态的web项目(解决方法)

    Eclipse Java Oxygen不能创建动态的web项目(解决方法) 一.eclipse安装J2EE插件 一.eclipse安装J2EE插件 Oxygen版本Eclipse没有toamct开发工 ...

  3. MySQL无法启动并提示file could not be found的解决方法

    今天在测试时就遇到了MySQL挂掉始终无法启动的问题,看了半天日志也没找出到底是怎么回事. [root@iZ23zpftdweZ ~]# /etc/init.d/mysql start Startin ...

  4. php源码 时间慢8小时 etc gmt,PHP 中 Date 函数与实际时间相差8小时的解决方法

    PHP 中的 date() 函数显示的时间是格林威治时间,和北京时间正好相差8个小时,其他时间相关的函数,如 strtotime() 也有相同的问题,同样可以通过下面的方法来解决: 1. 修改php. ...

  5. SQL Sever2012 创建表时发生“未指定错误”解决方法

    @[TOC]( SQL Sever2012 创建表时发生"未指定错误"解决方法 下载SQL2012,界面一般,而且从第二次使用时就发现,第一次创建的数据库都打不开,说是什么位置移动 ...

  6. 计算机加域成灰色,win7系统创建域选项变成灰色的解决方法

    win7系统使用久了,好多网友反馈说win7系统创建域选项变成灰色的问题,非常不方便.有什么办法可以永久解决win7系统创建域选项变成灰色的问题,面对win7系统创建域选项变成灰色故障问题,我们只需要 ...

  7. mybatis向mysql数据库插入数据时,中文乱码显示为?解决方法

    mybatis向mysql数据库插入数据时,中文乱码显示为?解决方法 1.先查看库.表.表字符字段的编码格式.MySQL默认的库和表的字符编码都是latin1,而我们一般需要使用 utf8 //先查看 ...

  8. Linux 中ifconfig和ip addr命令查看不到ip解决方法

    Linux 中ifconfig和ip addr命令查看不到ip解决方法 参考文章: (1)Linux 中ifconfig和ip addr命令查看不到ip解决方法 (2)https://www.cnbl ...

  9. mysql出现ERROR1698(28000):Access denied for user root@localhost错误解决方法

    mysql出现ERROR1698(28000):Access denied for user root@localhost错误解决方法 参考文章: (1)mysql出现ERROR1698(28000) ...

最新文章

  1. 加密移动硬盘解决方案
  2. C# 设置Menustrip提示框的显示
  3. R语言实战应用精讲50篇(三)-多重线性回归系列之模型评估与诊断应用案例
  4. 即将到来的 Android N 将具备这些新特性
  5. wpa_supplicant 无线网络配置
  6. 先查询后修改并发的时候sql_如何解决并发场景下扣款的数据一致性问题?
  7. 苹果手机怎么拍星空_手机怎么拍星空
  8. 【BZOJ-2400】Spoj839Optimal Marks 最小割 + DFS
  9. html滑动验证到最右边,jQuery滑块拖动到最右边验证插件
  10. 「程序猿 DD」星球活动第一期,将在 7 月 9 日晚 20:00 整开放!
  11. ~0 == -1 问题全解
  12. Swift学习笔记(四)
  13. 微信小程序的体验评分,如何从开发者工具中调取
  14. Cortex-A 系列处理器
  15. SAP中建立一个ODATA步骤
  16. 超详细 Zimbra 环境搭建安装
  17. 机房一体化监测解决方案
  18. android dat 乱码,微信dat文件打开乱码
  19. eleUi解决表单中el-select选择器比el-input输入框小的问题
  20. erp怎样修改服务器,erp服务器怎么设置

热门文章

  1. spring mvc中filter的设计与实现
  2. doctype的三种类型
  3. 微信朋友圈技术之道:三个人的后台团队与每日十亿的发布量
  4. 又拍云上传文件后,如何访问?
  5. 题目1051:数字阶梯求和
  6. 删除取消 excel 2007 自动生成的超链接
  7. ant design select 坑总结
  8. Java能抵挡住JavaScript的进攻吗?
  9. BZOJ 1631: [Usaco2007 Feb]Cow Party【最短路】
  10. select元素的各种jquery修改获取添加方法