MySQL中的timestamp数据类型

最近看了两篇关于timestamp的文章,正好手头有MySQL5的版本要升级。翻了翻版本5、6、7的文档,做了点笔记。

两篇博客地址:

MySQL的TIMESTAMP类型字段非空和默认值属性的影响

MySQL迁移后timestamp列cannot be null

date:

  日期。有效范围是‘1000-01-01’至‘9999-12-31’。检索和显示格式为‘YYYY-MM-DD’

datetime:

  包含日期和时间。有效范围是'1000-01-01 00:00:00'至'9999-12-31 23:59:59'。检索和显示格式为‘YYYY-MM-DD HH:MM:SS’

timestamp:

  包含日期和时间。有效范围是'1970-01-01 00:00:01' UTC至'2038-01-19 03:14:07' UTC。timestamp的值存储的是自'1970-01-01 00:00:00'但现在的秒数。timestamp不能存储1970-01-01 00:00:00‘’,因为这个表示经过了0秒,而0在timestamp中表示‘0000-00-00 00:00:00’。

 

在MySQL 5.5中,表中的第一个timestamp列如果没有显式指定内容,会自动被设置为最近修改的日期和时间。这使得timestamp列对于记录插入和更新的时间戳特别有用。如果将timestamp列指定为NULL,就表示将对应的列值设置成了当前的日期和时间。

如果开启了mixed sql mode,timestamp和datetime一样了。创建表的时候会将timestamp转换成datetime。从5.7.2开始,mixed sql mode变得过期了。

存储的时候,MySQL将timestamp的值从当前的时区转换成UTC时间进行存储;检索的时候从UTC转成当前的时区。(其它类型,如datetime不会有这种转换)。如果存储进去后修改过时区,就可能会检索出不同于原来的值。缺省情况下,每个连接的当前时区是mysql server的时区。

datetime或timestamp值可以包括尾随小数秒部分,精度最高可达微秒(6 位)。在MySQL5中,尽管可以识别此小数部分,但它会从存储在datetime或timestamp列中的值中丢弃。从MySQL5.6.4开始,这部分的值不再被丢弃。格式也就变成了'YYYY-MM-DD hh:mm:ss[.fraction]',datetime的取值范围变成了'1000-01-01 00:00:00.000000'至'9999-12-31 23:59:59.999999';timestamp的取值范围变成了'1970-01-01 00:00:01.000000'至'2038-01-19 03:14:07.999999'

无效的date、datetime、timestamp的值会被转换成适当的0格式,如('0000-00-00' 或'0000-00-00 00:00:00')。

MySQL中日期值解释的一些特性:

·MySQL允许指定为字符串的值的“宽松”格式,其中任何标点字符都可以用作日期部分或时间部分之间的分隔符。在某些情况下,这种语法可能具有欺骗性。例如,诸如“10:11:12”之类的值可能由于“:”分隔符而看起来像时间值,但如果在日期上下文中使用,则被解释为年份“2010-11-12”。 值“10:45:15”被转换为“0000-00-00”,因为“45”不是一个有效月份。

在日期和时间部分与小数秒部分之间识别的唯一分隔符是小数点。

·月和日值必须是有效的,而不仅仅是分别在1到12和1到31的范围内。禁用strict mode后,诸如“2004-04-31”之类的无效日期将转换为“0000-00-00”并生成警告;启用strict mode后,无效日期会产生错误。要允许此类日期,请启用 ALLOW_INVALID_DATES。

·MySQL不接受在日或月中包含零的TIMESTAMP值或无效日期的值。此规则的唯一例外是特殊的“零”值 '0000-00-00 00:00:00',前提是SQL mode允许此值。确切的行为取决于是否启用了strict sql模式和no_zero_date模式。

·包含2位数年份值的日期不明确,因为世纪未知。MySQL使用以下规则解释2位年份值:

--00-69范围内的年份值变为 2000-2069。

--70-99范围内的年份值变为 1970-1999。

 

MySQL5.5中的timestamp和datetime列的自动初始化和自动更新

timestamp数据类型具有自动初始化和更新成当前日期和时间(当前的时间戳)的功能。是否使用这些特性,由用户决定:

·一个表中只有一个timestamp列在初始化的时候可以用当前时间戳作为默认值或自动更新的值、或者同时作为默认值和自动更新值。但不能作为一个timestamp列的默认值、通过作为另一个timestamp列的自动更新值。

·如果timestamp列是自动初始化的,会将当前时间戳作为默认值

·如果timestamp列是自动更新的,行中任何列的修改都会将timestamp列修改成当前时间戳。

自动初始化或自动更新功能,可以通过关键字default current_timestamp、on update current_timestamp来指定。

如果指定了no_zero_data sql模式,就不可以指定为default 0了,0或‘0000-00-00 00:00:00’会被拒绝。

 

MySQL5.6中的timestamp和datetime列的自动初始化和自动更新

从5.6.5开始,timestamp和time列可以自动初始化或自动更新成当前时间戳,即current timestamp。

在5.6.5之前,只有timestamp列可以自动初始化或自动更新成当前时间戳,且一个表中最多只有一个timetamp列具备该特性。

对于表中的timestamp、datetime列,可以将当前时间戳指定为列的默认值、自动更新值、或者同时指定为默认值和自动更新值。

1.插入行时,将当前时间戳指定为自动初始值

2.行中列发生变更时,自动更新成当前时间戳;如果其他列的值被修改成当前的值,就会自动更新timestamp、datetime列的值

如果关闭了explicit_defaults_for_timestamp变量,可以通过指定为NULL值,将任何timestamp列(datetime列不是如此)初始化或更新成当前时间戳,列被定义为允许为NULL例外。

指定自动初始化、或自动更新属性,使用default current_timestamp、on update current_timestamp子句定义。二者的定义顺序不重要。

default语句也可以指定显式的默认值,比如default 0、default ‘2000-02-02 00:00:00’。default 0 是否会会产生警告或错误,取决于是否开启了strict sql mode或no_zero_date sql mode。

 

1.同时指定默认值和自动更新特性

create table t1 (
  ts timestamp default current_timestamp on update current_timestamp,
  dt datetime default current_timestamp on update current_timestamp
);

2.指定默认值

create table t1 (
  ts timestamp default current_timestamp,
  dt datetime default current_timestamp
);

像下面这样,就没有自动初始化和自动更新的特性了:

create table t1 (
  ts timestamp default 0,
  dt datetime default 0
);

3.指定默认常量值和自动更新

create table t1 (
  ts timestamp default 0 on update current_timestamp,
  dt datetime default 0 on update current_timestamp
);

4.指定自动更新

如果timestamp没有显式指定默认值为null,则其默认值是0;datetime的默认值是null,如果指定为not null,默认值是0。

create table t1 (
  ts1 timestamp on update current_timestamp,     -- default 0
  ts2 timestamp null on update current_timestamp -- default null
);
create table t1 (
  dt1 datetime on update current_timestamp,         -- default null
  dt2 datetime not null on update current_timestamp -- default 0
);

timestamp、datetime列如果没有显式定义,就不开启自动初始化和自动更新功能。但是也有例外,如果关闭了explicit_default_for_timestamp变量,第一个没有使用default current_timestamp、on update current_timestamp定义的timestamp列同时具备这两种属性。开启了explicit_default_for_timestamp变量,就必须显式定义才行。

来分析以下,如下定义的表:

create table t1 (
  ts1 timestamp default 0,
  ts2 timestamp default current_timestamp on update current_timestamp);
create table t2 (
  ts1 timestamp null,
  ts2 timestamp default current_timestamp on update current_timestamp);
create table t3 (
  ts1 timestamp null default 0,
  ts2 timestamp default current_timestamp on update current_timestamp);

 

·每个表中,第一个timestamp列没有定义自动初始化、自动更新的功能。

·表中ts1处理null值的方式是不同的,t1.ts1是not null,给其赋予NULL会将其值设置成当前时间戳;t2.ts1和t3.ts1支持null,给其赋予NULL就会将其值设置成NULL。

·t2.ts1支持null,默认值是null;t3.ts1支持null,但是默认值是0。

MySQL5.6之前自动初始化和自动更新存在以下限制:

1.default current_timestamp、on update current_timestamp不能用于datetime列。

2.每个表中只能有一个timestamp列使用default current_timestamp、on update current_timestamp。

timestamp初始化和null属性

如果explicit_defaults_for_timestamp变量被关闭了。timestamp列默认是not null的,不能包含null值;赋为null,会变成当前时间戳。如果想包含null值,需要显式定义null,这样的话默认值就是null

 

原文地址:https://www.cnblogs.com/abclife/p/15521401.html