Heim >Datenbank >MySQL-Tutorial >解析mysql TIMESTAMP(时间戳)和datetime不同之处比较
文章来介绍了mysql TIMESTAMP(时间戳) 的一用法特性以及TIMESTAMP和datetime函数的区别与不同之处,有需要了解此函数的朋友可以参考一下本文章。
TIMESTAMP基础知识介绍
TIMESTAMP的变体
1,TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 在创建新记录和修改现有记录的时候都对这个数据列刷新
2,TIMESTAMP DEFAULT CURRENT_TIMESTAMP 在创建新记录的时候把这个字段设置为当前时间,但以后修改时,不再刷新它
3,TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 在创建新记录的时候把这个字段设置为0,以后修改时刷新它
4,TIMESTAMP DEFAULT ‘yyyy-mm-dd hh:mm:ss’ ON UPDATE CURRENT_TIMESTAMP 在创建新记录的时候把这个字段设置为给定值,以后修改时刷新它
MySQL目前不支持列的Default 为函数的形式,如达到你某列的默认值为当前更新日期与时间的功能,你可以使用TIMESTAMP列类型下面就详细说明TIMESTAMP列类型
*TIMESTAMP列类型*
TIMESTAMP值可以从1970的某时的开始一直到2037年,精度为一秒,其值作为数字显示。
TIMESTAMP值显示尺寸的格式如下表所示:
:
+---------------+----------------+
| 列类型 | 显示格式 |
| TIMESTAMP(14) | YYYYMMDDHHMMSS |
| TIMESTAMP(12) | YYMMDDHHMMSS |
| TIMESTAMP(10) | YYMMDDHHMM |
| TIMESTAMP(8) | YYYYMMDD |
| TIMESTAMP(6) | YYMMDD |
| TIMESTAMP(4) | YYMM |
| TIMESTAMP(2) | YY |
+---------------+----------------+
“完整”TIMESTAMP格式是14位,但TIMESTAMP列也可以用更短的显示尺寸创造最常见的显示尺寸是6、8、12、和14。
你可以在创建表时指定一个任意的显示尺寸,但是定义列长为0或比14大均会被强制定义为列长14。
列长在从1~13范围的奇数值尺寸均被强制为下一个更大的偶数。
*列如:*
定义字段长度 强制字段长度
TIMESTAMP(0) -> TIMESTAMP(14)
TIMESTAMP(15)-> TIMESTAMP(14)
TIMESTAMP(1) -> TIMESTAMP(2)
TIMESTAMP(5) -> TIMESTAMP(6)
所有的TIMESTAMP列都有同样的存储大小,使用被指定的时期时间值的完整精度(14位)存储合法的值不考虑显示尺寸。不合法的日期,将会被强制为0存储
*这有几个含意: *
1、虽然你建表时定义了列TIMESTAMP(8),但在你进行数据插入与更新时TIMESTAMP列实际上保存了14位的数据(包括年月日时分秒),只不过在你进行查询时MySQL返回给你的是8位的年月日数据。如果你使用ALTER TABLE拓宽一个狭窄的TIMESTAMP列,以前被“隐蔽”的信息将被显示。
2、同样,缩小一个TIMESTAMP列不会导致信息失去,除了感觉上值在显示时,较少的信息被显示出。
3、尽管TIMESTAMP值被存储为完整精度,直接操作存储值的唯一函数是UNIX_TIMESTAMP();由于MySQL返回TIMESTAMP列的列值是进过格式化后的检索的值,这意味着你可能不能使用某些函数来操作TIMESTAMP列(例如HOUR()或SECOND()),除非TIMESTAMP值的相关部分被包含在格式化的值中。例如,一个TIMESTAMP列只有被定义为TIMESTAMP(10)以上时,TIMESTAMP列的HH部分才会被显示,因此在更短的TIMESTAMP值上使用HOUR()会产生一个不可预知的结果。
4、不合法TIMESTAMP值被变换到适当类型的“零”值(00000000000000)。(DATETIME,DATE亦然)
*你可以使用下列语句来验证:*
CREATE TABLE test ('id' INT (3) UNSIGNED AUTO_INCREMENT, 'date1'
TIMESTAMP (8) PRIMARY KEY('id'));
INSERT INTO test SET id = 1;
SELECT * FROM test;
+----+----------------+
| id | date1 |
+----+----------------+
| 1 | 20021114 |
+----+----------------+
ALTER TABLE test CHANGE 'date1' 'date1' TIMESTAMP(14);
SELECT * FROM test;
+----+----------------+
| id | date1 |
+----+----------------+
| 1 | 20021114093723 |
+----+----------------+
你可以使用TIMESTAMP列类型自动地用当前的日期和时间标记INSERT或UPDATE的操作。如果你有多个TIMESTAMP列,只有第一个自动更新。自动更新第一个TIMESTAMP列在下列任何条件下发生:
1、列值没有明确地在一个INSERT或LOAD DATA INFILE语句中指定。
2、列值没有明确地在一个UPDATE语句中指定且另外一些的列改变值。(注意一个UPDATE设置一个列为它已经有的值,这将不引起TIMESTAMP列被更新,因为如果你设置一个列为它当前的值,MySQL为了效率而忽略更改。)
3、你明确地设定TIMESTAMP列为NULL.
4、除第一个以外的TIMESTAMP列也可以设置到当前的日期和时间,只要将列设为NULL,或NOW()。
CREATE TABLE test (
'id' INT (3) UNSIGNED AUTO_INCREMENT,
'date1' TIMESTAMP (14),
'date2' TIMESTAMP (14),
PRIMARY KEY('id')
);
INSERT INTO test (id, date1, date2) VALUES (1, NULL, NULL);
INSERT INTO test SET id= 2;
+----+----------------+----------------+
| id | date1 | date2 |
+----+----------------+----------------+
| 1 | 20021114093723 | 20021114093723 |
| 2 | 20021114093724 | 00000000000000 |
+----+----------------+----------------+
->第一条指令因设date1、date2为NULL,所以date1、date2值均为当前时间第二条指令因没有设date1、date2列值,第一个TIMESTAMP列date1为更新为当前时间,而二个TIMESTAMP列date2因日期不合法而变为“00000000000000”
UPDATE test SET id= 3 WHERE id=1;
+----+----------------+----------------+
| id | date1 | date2 |
+----+----------------+----------------+
| 3 | 20021114094009 | 20021114093723 |
| 2 | 20021114093724 | 00000000000000 |
+----+----------------+----------------+
->这条指令没有明确地设定date2的列值,所以第一个TIMESTAMP列date1将被更新为当前时间
UPDATE test SET id= 1,date1=date1,date2=NOW() WHERE id=3;
+----+----------------+----------------+
| id | date1 | date2 |
+----+----------------+----------------+
| 1 | 20021114094009 | 20021114094320 |
| 2 | 20021114093724 | 00000000000000 |
+----+----------------+----------------+
->这条指令因设定date1=date1,所以在更新数据时date1列值并不会发生改变而因设定date2=NOW(),所以在更新数据时date2列值会被更新为当前时间此指令等效为 UPDATE test SET id= 1,date1=date1,date2=NULL WHERE id=3;
因MySQL返回的 TIMESTAMP 列为数字显示形式,你可以用DATE_FROMAT()函数来格式化 TIMESTAMP 列
SELECT id,DATE_FORMAT(date1,'%Y-%m-%d %H:%i:%s') As date1,
DATE_FORMAT(date2,'%Y-%m-%d %H:%i:%s') As date2 FROM test;
+----+---------------------+---------------------+
| id | date1 | date2 |
+----+---------------------+---------------------+
| 1 | 2002-11-14 09:40:09 | 2002-11-14 09:43:20 |
| 2 | 2002-11-14 09:37:24 | 0000-00-00 00:00:00 |
+----+---------------------+---------------------+
SELECT id,DATE_FORMAT(date1,'%Y-%m-%d') As date1,
DATE_FORMAT(date2,'%Y-%m-%d') As date2 FROM test;
+----+-------------+-------------+
| id | date1 | date2 |
+----+-------------+-------------+
| 1 | 2002-11-14 | 2002-11-14 |
| 2 | 2002-11-14 | 0000-00-00 |
+----+-------------+-------------+
在某种程度上,你可以把一种日期类型的值赋给一个不同的日期类型的对象。然而,而尤其注意的是:值有可能发生一些改变或信息的损失:
1、如果你将一个DATE值赋给一个DATETIME或TIMESTAMP对象,结果值的时间部分被设置为'00:00:00',因为DATE值中不包含有时间信息。
2、如果你将一个DATETIME或TIMESTAMP值赋给一个DATE对象,结果值的时间部分被删除,因为DATE类型不存储时间信息。
3、尽管DATETIME, DATE和TIMESTAMP值全都可以用同样的格式集来指定,但所有类型不都有同样的值范围。
例如,TIMESTAMP值不能比1970早,也不能比2037晚,这意味着,一个日期例如'1968-01-01',当作为一个DATETIME或DATE值时它是合法的,但它不是一个正确TIMESTAMP值!并且如果将这样的一个对象赋值给TIMESTAMP列,它将被变换为0。
*当指定日期值时,当心某些缺陷: *
1、允许作为字符串指定值的宽松格式能被欺骗。例如,,因为“:”分隔符的使用,值'10:11:12'可能看起来像时间值,但是如果在一个日期中使用,上下文将作为年份被解释成'2010-11-12'。值'10:45:15'将被变换到'0000-00-00',因为'45'不是一个合法的月份。
2、以2位数字指定的年值是模糊的,因为世纪是未知的。MySQL使用下列规则解释2位年值: 在00-69范围的年值被变换到2000-2069。 在范围70-99的年值被变换到1970-1999。
TIMESTAMP与datetime对比
相同
显示
TIMESTAMP列的显示格式与DATETIME列相同。换句话说,显示宽度固定在19字符,并且格式为YYYY-MM-DD HH:MM:SS。
不同
范围
datetime 以'YYYY-MM-DD HH:MM:SS'格式检索和显示DATETIME值。支持的范围为'1000-01-01 00:00:00'到'9999-12-31 23:59:59'TIMESTAMP值不能早于1970或晚于2037
储存
TIMESTAMP
1.4个字节储存(Time stamp value is stored in 4 bytes)
2.值以UTC格式保存( it stores the number of milliseconds)
3.时区转化 ,存储时对当前的时区进行转换,检索时再转换回当前的时区。
datetime
1.8个字节储存(8 bytes storage)
2.实际格式储存(Just stores what you have stored and retrieves the same thing which you have stored.)
3.与时区无关(It has nothing to deal with the TIMEZONE and Conversion.)
实例对比
现在我来做个时区对他们的影响。
1.先插入一个数据insert into `t8` values(now(), now());
2.改变客户端时区(东9区,日本时区)。
3.再次显示插入的数据,变化了,timestamp类型的数据 增加了 1个小时
接下来 讨论一些timestamp 的其他的属性
1.null 是否为空
timestamp 默认允许为 “非空”(not null by default), 如果你在定义“ts TIMESTAMP DEFAULT NULL” 是非法的。 可以指定为空 null ,“ts TIMESTAMP NULL" ,这时可以在添加语句改变默认值。
ts2 TIMESTAMP NULL DEFAULT 0,ts3 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP
default (一个表中只能有一个列选择下面其中一种)
default CURRENT_TIMESTAMP default CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP
ON UPDATE 见上2
MYSQL中TIMESTAMP简单实例
MYSQL中TIMESTAMP类型可以设定默认值,就像其他类型一样。
1、自动UPDATE 和INSERT 到当前的时间:
表:
/*DDL Information For - test.t1*/
---------------------------------
Table Create Table
------ -------------------------------------------------------------------------------------
t1 CREATE TABLE `t1` (
`p_c` int(11) NOT NULL,
`p_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=gb2312
数据:
1 2007-10-08 11:53:35
2 2007-10-08 11:54:00
insert into t1(p_c) select 3;
update t1 set p_c = 2 where p_c = 2;
数据:
1 2007-10-08 11:53:35
2 2007-10-08 12:00:37
3 2007-10-08 12:00:37
2、自动INSERT 到当前时间,不过不自动UPDATE。
表:
/*DDL Information For - test.t1*/
---------------------------------
Table Create Table
------ ---------------------------------------------------------
t1 CREATE TABLE `t1` (
`p_c` int(11) NOT NULL,
`p_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=gb2312
数据:
insert into t1(p_c) select 4;
update t1 set p_c = 3 where p_c = 3;
1 2007-10-08 11:53:35
2 2007-10-08 12:00:37
3 2007-10-08 12:00:37
4 2007-10-08 12:05:19
3、一个表中不能有两个字段默认值是当前时间,否则就会出错。不过其他的可以。
表:
/*DDL Information For - test.t1*/
---------------------------------
Table Create Table
------ ---------------------------------------------------------------
t1 CREATE TABLE `t1` (
`p_c` int(11) NOT NULL,
`p_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`p_timew2` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
) ENGINE=InnoDB DEFAULT CHARSET=gb2312
数据:
1 2007-10-08 11:53:35 0000-00-00 00:00:00
2 2007-10-08 12:00:37 0000-00-00 00:00:00
3 2007-10-08 12:00:37 0000-00-00 00:00:00
4 2007-10-08 12:05:19 0000-00-00 00:00:00