ITPub博客

首页 > 数据库 > > 11.2 日期和时间类型

11.2 日期和时间类型

作者:飘絮絮絮丶 时间:2020-05-12 10:55:49 0 删除 编辑

参考官方文档:

dev.mysql.com/doc/refma




对于DATE和DATETIME范围描述,“支持”意味着虽然较早的值可能有效,但不能保证


MySQL允许TIME,DATETIME和TIMESTAMP值的分数秒,精度可达几微秒(6位)。 要定义包含小数秒部分的列,请使用语法type_name(fsp),其中type_name是TIME,DATETIME或TIMESTAMP,而fsp是小数秒精度。 例如:


CREATE TABLE t1 (t TIME(3), dt DATETIME(6));


如果给出,fsp值必须在0到6的范围内。值为0表示没有小数部分。 如果省略,则默认精度为0.(这与标准SQL缺省值6不同,以便与以前的MySQL版本兼容。)



表中的任何TIMESTAMP或DATETIME列都可以具有自动初始化和更新属性。



  • DATE



date。 支持的范围是'1000-01-01'到'9999-12-31'。 MySQL以'YYYY-MM-DD'格式显示DATE值,但允许使用字符串或数字将值分配给DATE列。


  • DATETIME[(fsp)]


日期和时间组合。 支持的范围是'1000-01-01 00:00:00.000000'至'9999-12-31 23:59:59.999999'。 MySQL以'YYYY-MM-DD HH:MM:SS [.fraction]'格式显示DATETIME值,但允许使用字符串或数字将值分配给DATETIME列。


可以给出0到6范围内的可选fsp值来指定小数秒精度。 值为0表示不存在小数部分。 如果省略,则默认精度为0。


如第11.3.5节“自动初始化和更新TIMESTAMP和DATETIME”中所述,可以使用DEFAULT和ON UPDATE列定义子句来指定DATETIME列的当前日期和时间的自动初始化和更新。



  • TIMESTAMP[(fsp)]


时间戳。 范围为'1970-01-01 00:00:01.000000'UTC至'2038-01-19 03:14:07.999999'UTC。 TIMESTAMP值存储为自纪元以来的秒数('1970-01-01 00:00:00'UTC)。 一个TIMESTAMP不能表示值'1970-01-01 00:00:00',因为它相当于从纪元0秒,值0保留代表'0000-00-00 00:00:00', “零”TIMESTAMP值。


可以给出0到6范围内的可选fsp值来指定小数秒精度。 值为0表示不存在小数部分。 如果省略,则默认精度为0。


服务器处理TIMESTAMP定义的方式取决于explicit_defaults_for_timestamp系统变量的值(请参见第5.1.5节“服务器系统变量”)。


如果启用了explicit_defaults_for_timestamp,则不会自动将DEFAULT CURRENT_TIMESTAMP或ON UPDATE CURRENT_TIMESTAMP属性分配给任何TIMESTAMP列。 它们必须明确包含在列定义中。 而且,任何未明确声明为NOT NULL的TIMESTAMP都允许NULL值。


如果禁用了explicit_defaults_for_timestamp,则服务器按如下方式处理TIMESTAMP:


除非另有规定,否则表中的第一个TIMESTAMP列被定义为如果未明确赋值,则自动设置为最近修改的日期和时间。 这使得TIMESTAMP可用于记录INSERT或UPDATE操作的时间戳。 除非使用NULL属性定义来允许NULL,才可以为TIMESTAMP字段属性分配NULL。


可以使用DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP列定义子句来指定自动初始化和更新到当前日期和时间。 如前所述,默认情况下,第一个TIMESTAMP列具有这些属性。 但是,可以将表中的任何TIMESTAMP列定义为具有这些属性。



  • TIME[(fsp)]


time。 范围是'-838:59:59.000000'到'838:59:59.000000'。 MySQL以'HH:MM:SS [.fraction]'格式显示TIME值,但允许使用字符串或数字将值分配给TIME列。


可以给出0到6范围内的可选fsp值来指定小数秒精度。 值为0表示不存在小数部分。 如果省略,则默认精度为0


  • YEAR[(4)]

一年四位数的格式。 MySQL以YYYY格式显示YEAR值,但允许使用字符串或数字将值分配给YEAR列。 值显示为1901至2155和0000。


注意:


YEAR(2)数据类型已被弃用,并且在MySQL 5.7.5中删除了对它的支持。 要将YEAR(2)列转换为YEAR(4),请参见第11.3.4节“YEAR(2)限制和迁移到YEAR(4)”。


SUM()和AVG()聚合函数不适用于时间值。 (它们将值转换为数字,在第一个非数字字符后丢失所有内容。)要解决此问题,请转换为数值单位,执行聚合操作并转换回时间值。 例子:

SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(time_col))) FROM tbl_name; SELECT FROM_DAYS(SUM(TO_DAYS(date_col))) FROM tbl_name;


注意:


MySQL服务器可以在启用MAXDB SQL模式的情况下运行。 在这种情况下,TIMESTAMP与DATETIME相同。 如果在创建表时启用此模式,则TIMESTAMP列将创建为DATETIME列。 因此,这些列使用DATETIME显示格式,具有相同的值范围,并且没有自动初始化或更新到当前日期和时间。

从MySQL 5.7.22开始,不推荐使用MAXDB。 它将在未来版本的MySQL中被删除。

在处理日期和时间类型时请记住以下一般注意事项:


  • MySQL以标准输出格式检索给定日期或时间类型的值,但它试图解释您提供的输入值的各种格式(例如,当您指定要分配给日期或与日期比较的值或 时间类型)。 有关日期和时间类型的允许格式的说明,请参见第9.1.3节“日期和时间文字”。 预计您会提供有效的值。 如果您使用其他格式的值,则可能会出现不可预知的结果。
  • 虽然MySQL试图以多种格式解释值,但日期部分必须始终以年 - 月 - 日的顺序(例如,'98-09-04')给出,而不是以月 - 日 - 年或日 - 月 - (例如,'09 -04-98','04 -09-98')。
  • 包含两位数年份值的日期含糊不清,因为该世纪未知。 MySQL使用这些规则解释两位数年份值:
    • 在70-99范围内的年份值被转换为1970-1999。
    • 00-69范围内的年份值转换为2000-2069。
  • 根据第11.3.7节“日期和时间类型之间的转换”中的规则,将值从一种时间类型转换为另一种时间类型。
  • 如果在数值上下文中使用该值,MySQL会自动将日期或时间值转换为数字,反之亦然。
  • 默认情况下,当MySQL遇到一个超出范围的日期或时间类型的值或者对该类型无效时,它会将该值转换为该类型的“零”值。 例外情况是超出范围的TIME值被剪切到TIME范围的适当端点。
  • 通过将SQL模式设置为适当的值,您可以更确切地指定希望MySQL支持的日期类型。 (请参见第5.1.8节“服务器SQL模式”。)通过启用ALLOW_INVALID_DATES SQL模式,您可以让MySQL接受某些日期,例如'2009-11-31'。 当您想要将用户在数据库中指定的“可能错误”值(例如,在Web表单中)存储以供将来处理时,这非常有用。 在这种模式下,MySQL仅验证月份是在1到12的范围内,并且该日期在1到31的范围内。
  • MySQL允许您在DATE或DATETIME列中存储日期或月份和日期为零的日期。 这对需要存储生日的应用程序非常有用,因为您可能不知道确切的日期。 在这种情况下,您只需将日期存储为“2009-00-00”或“2009-01-00”。 如果您存储这些日期,则不应期望得到需要完整日期的函数(如DATE_SUB()或DATE_ADD())的正确结果。 要在日期中禁止零月或日部分,请启用NO_ZERO_IN_DATE模式。
  • MySQL允许您将“0000-00-00”的“零”值存储为“虚拟日期”。这在某些情况下比使用NULL值更方便,并且使用更少的数据和索引空间。 要禁止'0000-00-00',请启用NO_ZERO_DATE模式。
  • 通过Connector / ODBC使用的“零”日期或时间值会自动转换为NULL,因为ODBC无法处理这些值。


下表显示了每种类型的“零”值的格式。 “零”值是特殊的,但您可以使用表中显示的值显式存储或引用它们。 您也可以使用值更容易编写的值“0”或0来执行此操作。 对于包含日期部分(DATE,DATETIME和TIMESTAMP)的时态类型,如果启用NO_ZERO_DATE SQL模式,则使用这些值会产生警告。




11.3.1 DATE,DATETIME,和TIMESTAMP 类型



DATE,DATETIME和TIMESTAMP类型是相关的。 本节介绍它们的特点,它们的相似之处以及它们的不同之处。 MySQL以几种格式识别DATE,DATETIME和TIMESTAMP值,如第9.1.3节“日期和时间文字”中所述。 对于DATE和DATETIME范围描述,“支持”意味着虽然较早的值可能有效,但不能保证。



Date 类型只有日期部分,但是没有时间部分。MySQL以'YYYY-MM-DD'格式检索并显示DATE值。 支持的范围是'1000-01-01'到'9999-12-31'。


DATETIME类型用于包含日期和时间部分的值。 MySQL以'YYYY-MM-DD HH:MM:SS'格式检索并显示DATETIME值。 支持的范围是'1000-01-01 00:00:00'到'9999-12-31 23:59:59'。


TIMESTAMP数据类型用于包含日期和时间部分的值。 TIMESTAMP的范围为'1970-01-01 00:00:01'UTC至'2038-01-19 03:14:07'UTC。



DATETIME或TIMESTAMP值可以包含以微秒(6位数)为精度的尾随小数秒部分。 特别是,插入到DATETIME或TIMESTAMP列的值中的任何小数部分都被存储而不是丢弃。 在包含小数部分的情况下,这些值的格式为'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'。 小数部分应始终与其余时间分开小数点; 没有其他小数分隔符被识别。


TIMESTAMP和DATETIME数据类型提供了对当前日期和时间的自动初始化和更新。


MySQL将TIMESTAMP值从当前时区转换为UTC存储,并从UTC转回当前时区以供检索。 (对于其他类型(如DATETIME),不会发生这种情况。)默认情况下,每个连接的当前时区是服务器的时间。 时区可以基于每个连接进行设置。 只要时区设置保持不变,您可以获得到与存储的相同值。 如果您存储TIMESTAMP值,然后更改时区并检索该值,则检索到的值与您存储的值不同。 发生这种情况是因为同一时区无双向转换。 当前时区可用作time_zone系统变量的值。


无效的DATE,DATETIME或TIMESTAMP值将转换为相应类型('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的范围内。 禁用严格模式后,无效日期(如“2004-04-31”)将转换为“0000-00-00”,并生成警告。 启用严格模式后,无效日期会生成错误。 要允许这种日期,请启用ALLOW_INVALID_DATES。
  • MySQL不接受在日期或月份列中包含零的TIMESTAMP值或不是有效日期的值。 这条规则的唯一例外是特殊的“零”值“0000-00-00 00:00:00”。
  • 包含两位数年份值的日期含糊不清,因为该世纪未知。 MySQL使用这些规则解释两位数年份值:
    • 00-69范围内的年份值转换为2000-2069。
    • 在70-99范围内的年份值被转换为1970-1999。


注意:

MySQL服务器可以在启用MAXDB SQL模式的情况下运行。 在这种情况下,TIMESTAMP与DATETIME相同。 如果在创建表时启用此模式,则TIMESTAMP列将创建为DATETIME列。 因此,这些列使用DATETIME显示格式,具有相同的值范围,并且没有自动初始化或更新到当前日期和时间。


从MySQL 5.7.22开始,不推荐使用MAXDB。 它将在未来版本的MySQL中被删除。



11.3.2 Time 类型


MySQL以 'HH:MM:SS'格式(或'HHH:MM:SS'格式获取大时间值)检索并显示TIME值。 TIME值可以从'-838:59:59'到'838:59:59'。 小时部分可能非常大,因为TIME类型不仅可用于表示一天中的时间(必须小于24小时),还可用于表示两个事件之间的经过时间或时间间隔(可能大于 24小时,甚至负值)。


MySQL以多种格式识别TIME值,其中一些格式可以包含最高达微秒(6位)精度的尾随小数秒部分。 请参见第9.1.3节“日期和时间文字”。 有关MySQL中小数秒支持的信息,请参见第11.3.6节“小数秒的时间值”。 特别是插入到TIME列的值中的任何小数部分都被存储而不是丢弃。 在包含小数部分的情况下,TIME值的范围为'-838:59:59.000000'至'838:59:59.000000'。

小心将缩略值分配给TIME列。 MySQL使用冒号解释时间缩短的TIME值,作为一天中的时间。 即'11:12'的意思是'11:12:00',而不是'00:11:12'。 MySQL使用假设两个最右边的数字表示秒(即过去的时间而不是一天中的时间)来解释缩写值。 例如,你可能认为'1112'和1112意味着'11:12:00',但MySQL将其解释为'00:11:12'(11分12秒)。 类似地,'12'和12被解释为'00:00:12'。


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


默认情况下,位于TIME范围之外但其他方式有效的值将剪切到范围的最近端点。 例如,'-850:00:00'和'850:00:00'被转换为'-838:59:59'和'838:59:59'。 无效的TIME值被转换为'00:00:00'。 请注意,因为'00:00:00'本身是一个有效的TIME值,所以无法从表中存储的值'00:00:00'中判断原始值是否被指定为'00:00:00'或其是无效的



11.3.3 YEAR 类型


YEAR类型是用于表示年份值的1字节类型。 它可以被声明为YEAR或YEAR(4)并且具有四个字符的显示宽度。

MySQL以YYYY格式显示YEAR值,范围从1901到2155或0000。


您可以指定各种格式的输入YEAR值:

  • 作为4-位数值,范围为1901到2155.
  • 作为4-位字符串,范围为'1901'到 '2155'
  • 作为1或2位,范围为1到99的数字.MySQL将范围1到69和70到99中的值转换为范围2001到2069和1970到1999范围内的YEAR值。
  • 作为在'0'至'99'的1或2位字符串。 MySQL将范围'0'到'69'和'70'到'99'的值转换为2000到2069和1970到1999年的YEAR值。
  • 插入数字0的结果显示值为0000,内部值为0000.要插入零并将其解释为2000,请将其指定为字符串'0'或'00'。
  • 作为返回YEAR上下文中可接受值的函数(如NOW())的函数的结果。


MYSQL 转换无效YEAR 值到0000


11.3.5 TIMESTAMP和DATETIME的自动初始化和更新


TIMESTAMP和DATETIME列可以自动初始化并更新为当前日期和时间(即当前时间戳)。


对于表中的任何TIMESTAMP或DATETIME列,可以将当前时间戳分配为默认值,自动更新值或both:

  • 一个自动初始化的列被设置为插入行的当前时间戳,这些行不为列指定值。
  • 当行中任何其他列的值从其当前值更改时,自动更新列会自动更新为当前时间戳。 如果所有其他列都设置为其当前值,则自动更新的列保持不变。 为了防止在其他列更改时自动更新列,请将其显式设置为其当前值。 要更新自动更新的列,即使其他列不更改,也要显式地将其设置为它应具有的值(例如,将其设置为CURRENT_TIMESTAMP)。


--自动更新用的比较少,一般是记录一下当前的时间戳。


另外,如果explicit_defaults_for_timestamp系统变量被禁用,则可以通过为任何TIMESTAMP(而不是DATETIME)列初始化或更新为当前日期和时间,方法是为它分配一个NULL值,除非它已使用NULL属性定义为允许NULL值。


要指定自动属性,请使用列定义中的DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP子句。 子句的顺序无关紧要。 如果两者都出现在列定义中,则都可以先发生。 CURRENT_TIMESTAMP的任何同义词的含义与CURRENT_TIMESTAMP相同。 这些是CURRENT_TIMESTAMP(),NOW(),LOCALTIME,LOCALTIME(),LOCALTIMESTAMP和LOCALTIMESTAMP()。

使用DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP特定于TIMESTAMP和DATETIME。 DEFAULT子句也可以用来指定一个常量(非自动)的默认值; 例如,DEFAULT 0或DEFAULT'2000-01-01 00:00:00'。


注意:

以下示例使用DEFAULT 0,根据严格SQL模式或NO_ZERO_DATE SQL模式是否启用,默认值可以产生警告或错误。 请注意,TRADITIONAL SQL模式包括严格模式和NO_ZERO_DATE。


TIMESTAMP或DATETIME列定义可以为默认值和自动更新值指定当前时间戳,或只指定一个,或者都不指定。 不同的列可以具有不同的自动属性组合。 以下规则描述了可能性:


  • 使用DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP,该列具有当前时间戳作为其默认值,并自动更新为当前时间戳。

CREATE TABLE t1 ( ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, dt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP );

  • 使用DEFAULT子句但不包含ON UPDATE CURRENT_TIMESTAMP子句,该列具有给定的默认值,并且不会自动更新为当前时间戳。

缺省取决于DEFAULT子句是指定CURRENT_TIMESTAMP还是一个常数值。 使用CURRENT_TIMESTAMP时,默认值是当前时间戳。


CREATE TABLE t1 ( ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP, dt DATETIME DEFAULT CURRENT_TIMESTAMP );


使用常量,默认值是给定的值。 在这种情况下,该列根本没有自动属性。


CREATE TABLE t1 ( ts TIMESTAMP DEFAULT 0, dt DATETIME DEFAULT 0 );

  • 使用ON UPDATE CURRENT_TIMESTAMP子句和常量DEFAULT子句,该列将自动更新为当前时间戳并具有给定的常量默认值。

CREATE TABLE t1 ( ts TIMESTAMP DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP, dt DATETIME DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP );

  • 使用ON UPDATE CURRENT_TIMESTAMP子句但没有DEFAULT子句,该列将自动更新为当前时间戳,但没有当前时间戳作为其默认值。

在这种情况下的默认值是依赖于类型的。 除非使用NULL属性定义,否则TIMESTAMP的默认值为0,在这种情况下,默认值为NULL。


CREATE TABLE t1 (

ts1 TIMESTAMP ON UPDATE CURRENT_TIMESTAMP -- default 0

ts2 TIMESTAMP NULL ON UPDATE CURRENT_TIMESTAMP -- default NULL );


除非使用NOT NULL属性定义,否则DATETIME的默认值为NULL,在这种情况下,默认值为0。


CREATE TABLE t1 (

dt1 DATETIME ON UPDATE CURRENT_TIMESTAMP, -- default NULL

dt2 DATETIME NOT NULL ON UPDATE CURRENT_TIMESTAMP -- default 0 );


TIMESTAMP和DATETIME列除非明确指定,否则不具有自动属性,但有以下例外情况:如果禁用了explicit_defaults_for_timestamp系统变量(默认禁用),则第一个TIMESTAMP列同时具有DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP(如果没有明确指定)。 要禁止第一个TIMESTAMP列的自动属性,请使用以下策略之一:

  • 启用explicit_defaults_for_timestamp系统变量。 在这种情况下,指定自动初始化和更新的DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP子句可用,但除非明确包含在列定义中,否则不会分配给任何TIMESTAMP列
  • 另外,如果 explicit_defaults_for_timestamp 被禁用,执行以下任一操作:
    • 使用指定常量默认值的DEFAULT子句定义列。
    • 指定NULL属性。 这也会导致列允许NULL值,这意味着您无法通过将列设置为NULL来分配当前时间戳。 分配NULL将列设置为NULL,而不是当前时间戳。 要分配当前时间戳,请将列设置为CURRENT_TIMESTAMP或NOW()等同义词。


考虑这些表定义:


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不为NULL,并将其赋值为NULL将其设置为当前时间戳。 对于t2和t3,ts1允许NULL并将其赋值为NULL将其设置为NULL。
  • t2和t3的ts1的默认值不同。 对于t2,ts1被定义为允许NULL,因此如果没有明确的DEFAULT子句,缺省值也是NULL。 对于t3,ts1允许NULL但显式默认值为0。


如果TIMESTAMP或DATETIME列定义在任何地方包含显式小数秒精度值,则必须在整个列定义中使用相同的值。 这是允许的:


CREATE TABLE t1 ( ts TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) );


这是不允许的:

CREATE TABLE t1 ( ts TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(3) );


TIMESTAMP 初始化和NULL 属性


如果explicit_defaults_for_timestamp系统变量被禁用,默认情况下TIMESTAMP列是NOT NULL,不能包含NULL值,并且分配NULL时设置为当前时间戳。 要允许TIMESTAMP列包含NULL,请使用NULL属性显式声明它。 在这种情况下,除非使用指定不同默认值的DEFAULT子句重写,否则缺省值也变为NULL。 可以使用DEFAULT NULL来显式指定NULL作为默认值。 (对于未用NULL属性声明的TIMESTAMP列,DEFAULT NULL无效。)如果TIMESTAMP列允许NULL值,则分配NULL将其设置为NULL,而不是当前时间戳。


下表包含允许NULL值的几个TIMESTAMP列:


CREATE TABLE t (

ts1 TIMESTAMP NULL DEFAULT NULL,

ts2 TIMESTAMP NULL DEFAULT 0,

ts3 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP );


除下列条件之一外,允许NULL值的TIMESTAMP列在插入时不会用当前时间戳:


  • 其默认值定义为CURRENT_TIMESTAMP,并且没有为列指定值
  • CURRENT_TIMESTAMP或其任何同义词,如NOW()明确插入列中


换句话说,定义为允许NULL值的TIMESTAMP列只有在其定义包含DEFAULT CURRENT_TIMESTAMP时才会自动初始化:

CREATE TABLE t (ts TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP);


如果TIMESTAMP列允许NULL值但其定义不包含DEFAULT CURRENT_TIMESTAMP,则必须显式插入与当前日期和时间相对应的值。 假设表t1和t2具有这些定义:


CREATE TABLE t1 (ts TIMESTAMP NULL DEFAULT '0000-00-00 00:00:00');

CREATE TABLE t2 (ts TIMESTAMP NULL DEFAULT NULL);


要在插入时将任一表中的TIMESTAMP列设置为当前时间戳,请明确地为其分配该值。 例如:

INSERT INTO t2 VALUES (CURRENT_TIMESTAMP);

INSERT INTO t1 VALUES (NOW());



如果启用了explicit_defaults_for_timestamp系统变量,则只有使用NULL属性声明时,TIMESTAMP列才允许NULL值。 另外,TIMESTAMP列不允许分配NULL来分配当前时间戳,无论是用NULL还是NOT NULL属性声明。 要分配当前时间戳,请将列设置为CURRENT_TIMESTAMP或NOW()等同义词。


11.3.6 在time值中的局部秒


MySQL 5.7对TIME,DATETIME和TIMESTAMP值提供小数秒的支持,最高可达微秒(6位)精度:

  • 要定义包含小数秒部分的列,请使用语法type_name(fsp),其中type_name是TIME,DATETIME或TIMESTAMP,而fsp是小数秒精度。 例如:

CREATE TABLE t1 (t TIME(3), dt DATETIME(6));


如果给出,fsp值必须在0到6的范围内。值为0表示没有小数部分。 如果省略,则默认精度为0.(这与标准SQL缺省值6不同,以便与以前的MySQL版本兼容。)

  • 将具有小数秒部分的TIME,DATE或TIMESTAMP值插入到相同类型的列中,但分数更少会导致舍入,如下例所示:


mysql> CREATE TABLE fractest( c1 TIME(2), c2 DATETIME(2), c3 TIMESTAMP(2) ); Query OK, 0 rows affected (0.33 sec)

mysql> INSERT INTO fractest VALUES

> ('17:51:04.777', '2014-09-08 17:51:04.777', '2014-09-08 17:51:04.777');

Query OK, 1 row affected (0.03 sec)

mysql> SELECT * FROM fractest;

+-------------+------------------------+------------------------+

| c1 | c2 | c3 |

+-------------+------------------------+------------------------+

| 17:51:04.78 | 2014-09-08 17:51:04.78 | 2014-09-08 17:51:04.78 |

+-------------+------------------------+------------------------+

1 row in set (0.00 sec)


--这里出现了四舍五入

发生舍入时不会发出警告或错误。 此行为遵循SQL标准,并且不受服务器的sql_mode设置的影响。


  • 带时态参数的函数接受小数秒的值。 时间函数的返回值包括适当的小数秒。 例如,不带参数的NOW()返回没有小数部分的当前日期和时间,但采用从0到6的可选参数来指定返回值包含该许多数字的小数部分。
  • 时态文字的语法产生时间值:DATE'str',TIME'str'和TIMESTAMP'str',以及与ODBC等效的语法。 如果指定小数部分,则结果值包含尾随小数秒。 以前,时态类型关键字被忽略,这些结构产生字符串值。



11.3.7 在Date 和Time 类型之间进行转换


在某种程度上,您可以将一个值从一个时间类型转换为另一个时间类型。 但是,值可能会有所改变或丢失信息。 在所有情况下,时态类型之间的转换都取决于结果类型的有效值范围。 例如,虽然DATE,DATETIME和TIMESTAMP值都可以使用相同的一组格式来指定,但这些类型并不都具有相同的值范围。 TIMESTAMP值不能早于1970年UTC或晚于'2038-01-19 03:14:07'UTC。 这意味着诸如“1968-01-01”之类的日期作为DATE或DATETIME值有效,但作为TIMESTAMP值无效并转换为0。


转换DATE 值:

  • 转换为DATETIME或TIMESTAMP值会添加'00:00:00'的时间部分,因为DATE值不包含时间信息。
  • 转换为TIME值不会有用; 结果是'00:00:00'。

转换 DATETIME 和TIMESTAMP 值:

  • 转换为DATE值需要考虑小数秒,并舍入时间部分。 例如,'1999-12-31 23:59:59.499'变成'1999-12-31',而'1999-12-31 23:59:59.500'变成'2000-01-01'。
  • 转换为TIME值会丢弃日期部分,因为TIME类型不包含日期信息。


为了将TIME值转换为其他时间类型,CURRENT_DATE()的值用于日期部分。 时间被解释为经过时间(不是一天中的时间)并添加到日期。 这意味着如果时间值超出“00:00:00”到“23:59:59”范围之外,结果的日期部分与当前日期不同。


假设当前日期是'2012-01-01'。 当转换为DATETIME或TIMESTAMP值时,'12:00:00','24:00:00'和'-12:00:00'的TIME值会导致'2012-01-01 12:00:00 ','2012-01-02 00:00:00'和'2011-12-31 12:00:00'。


TIME到DATE的转换类似,但分别从结果'2012-01-01','2012-01-02'和'2011-12-31'丢弃时间部分。


显式转换可用于覆盖隐式转换。 例如,通过比较DATE和DATETIME值,通过添加'00:00:00'的时间部分将DATE值强制为DATETIME类型。 要通过忽略DATETIME值的时间部分来执行比较,请按以下方式使用CAST()函数:


date_col = CAST(datetime_col AS DATE)



将TIME和DATETIME值转换为数字形式(例如,通过加上+0)取决于该值是否包含小数秒部分。 当N为0(或省略)时,TIME(N)或DATETIME(N)转换为整数,当N大于0时转换为具有N个小数位的DECIMAL值:


mysql> SELECT CURTIME(), CURTIME()+0, CURTIME(3)+0;

+-----------+-------------+--------------+

| CURTIME() | CURTIME()+0 | CURTIME(3)+0 |

+-----------+-------------+--------------+

| 09:28:00 | 92800 | 92800.887 |

+-----------+-------------+--------------+

mysql> SELECT NOW(), NOW()+0, NOW(3)+0;

+---------------------+----------------+--------------------+

| NOW() | NOW()+0 | NOW(3)+0 |

+---------------------+----------------+--------------------+

| 2012-08-15 09:28:00 | 20120815092800 | 20120815092800.889 |

+---------------------+----------------+------

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69946831/viewspace-3128048/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2019-09-09

  • 博文量
    2646
  • 访问量
    42158