首页 > 数据库 > > 11.2 日期和时间类型
参考官方文档:
https://dev.mysql.com/doc/refman/5.7/en/date-and-time-type-overview.html
对于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。 支持的范围是'1000-01-01'到'9999-12-31'。 MySQL以'YYYY-MM-DD'格式显示DATE值,但允许使用字符串或数字将值分配给DATE列。
日期和时间组合。 支持的范围是'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列的当前日期和时间的自动初始化和更新。
时间戳。 范围为'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。 范围是'-838:59:59.000000'到'838:59:59.000000'。 MySQL以'HH:MM:SS [.fraction]'格式显示TIME值,但允许使用字符串或数字将值分配给TIME列。
可以给出0到6范围内的可选fsp值来指定小数秒精度。 值为0表示不存在小数部分。 如果省略,则默认精度为0
一年四位数的格式。 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中被删除。
在处理日期和时间类型时请记住以下一般注意事项:
下表显示了每种类型的“零”值的格式。 “零”值是特殊的,但您可以使用表中显示的值显式存储或引用它们。 您也可以使用值更容易编写的值“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服务器可以在启用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值:
MYSQL 转换无效YEAR 值到0000
11.3.5 TIMESTAMP和DATETIME的自动初始化和更新
TIMESTAMP和DATETIME列可以自动初始化并更新为当前日期和时间(即当前时间戳)。
对于表中的任何TIMESTAMP或DATETIME列,可以将当前时间戳分配为默认值,自动更新值或both:
--自动更新用的比较少,一般是记录一下当前的时间戳。
另外,如果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列定义可以为默认值和自动更新值指定当前时间戳,或只指定一个,或者都不指定。 不同的列可以具有不同的自动属性组合。 以下规则描述了可能性:
CREATE TABLE t1 ( ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, dt DATETIME DEFAULT CURRENT_TIMESTAMP 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 );
CREATE TABLE t1 ( ts TIMESTAMP DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP, dt DATETIME DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP );
在这种情况下的默认值是依赖于类型的。 除非使用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列的自动属性,请使用以下策略之一:
考虑这些表定义:
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或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列在插入时不会用当前时间戳:
换句话说,定义为允许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位)精度:
CREATE TABLE t1 (t TIME(3), dt DATETIME(6));
如果给出,fsp值必须在0到6的范围内。值为0表示没有小数部分。 如果省略,则默认精度为0.(这与标准SQL缺省值6不同,以便与以前的MySQL版本兼容。)
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设置的影响。
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 值:
为了将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/ ,如需转载,请注明出处,否则将追究法律责任。