zoukankan      html  css  js  c++  java
  • 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

     

  • 相关阅读:
    Java实现 LeetCode 27 移除元素
    Java实现 LeetCode 26 删除排序数组中的重复项
    Java实现 LeetCode 26 删除排序数组中的重复项
    Java实现 LeetCode 26 删除排序数组中的重复项
    Java实现 LeetCode 25 K个一组翻转链表
    Java实现 LeetCode 25 K个一组翻转链表
    Java实现 LeetCode 25 K个一组翻转链表
    Java实现 LeetCode 24 两两交换链表中的节点
    Java实现 LeetCode 24 两两交换链表中的节点
    Java实现 LeetCode 24 两两交换链表中的节点
  • 原文地址:https://www.cnblogs.com/abclife/p/15521401.html
Copyright © 2011-2022 走看看