一、MySQL 中日期和时间类型
类型 | 大小(字节) | 范围 | 格式 | 用途 | 默认值设置 |
---|---|---|---|---|---|
DATE | 3 | 1000-01-01/9999-12-31 | YYYY-MM-DD | 日期值 | |
TIME | 3 | '-838:59:59'/'838:59:59' | HH:MM:SS | 时间值或持续时间 | |
YEAR | 1 | 1901/2155 | YYYY | 年份值 | |
DATETIME | 8 | 1000-01-01 00:00:00/9999-12-31 23:59:59 | YYYY-MM-DD HH:MM:SS | 混合日期和时间值 | |
TIMESTAMP | 4 | 1970-01-01 00:00:00/2038 结束时间是第 2147483647 秒,北京时间 2038-1-19 11:14:07,格林尼治时间 2038年1月19日 凌晨 03:14:07 | YYYYMMDD HHMMSS | 混合日期和时间值,时间戳 | 设置默认时间:CURRENT_TIMESTAMP 设置更新时间:ON UPDATE CURRENT_TIMESTAMP |
官方介绍:
- https://dev.mysql.com/doc/internals/en/date-and-time-data-type-representation.html
- https://dev.mysql.com/doc/refman/5.7/en/fractional-seconds.html
二、MySQL5.6.4 以后时间类型(DATETIME、TIMESTAMP、TIME)支持微秒
精确级别 | 类型 | 范围 | 默认值设置 |
---|---|---|---|
微秒 | DATETIME(6) | '1000-01-01 00:00:00.000000' to '9999-12-31 23:59:59.999999' | |
TIMESTAMP(6) | '1970-01-01 00:00:01.000000' to'2038-01-19 03:14:07.999999' | 设置默认时间:CURRENT_TIMESTAMP(6) 设置更新时间:ON UPDATE CURRENT_TIMESTAMP(6) | |
TIME(6) | ‘-838:59:59.000000’ to '838:59:59.000000' | ||
毫秒 | DATETIME(3) | '1000-01-01 00:00:00.000' to '9999-12-31 23:59:59.999' | |
TIMESTAMP(3) | '1970-01-01 00:00:01.000' to'2038-01-19 03:14:07.999' | 设置默认时间:CURRENT_TIMESTAMP(3) 设置更新时间:ON UPDATE CURRENT_TIMESTAMP(3) | |
TIME(3) | ‘-838:59:59.000’ to '838:59:59.000' |
三、举个栗子:MySQL 将时间存储为 数值数据类型(以毫秒为例,微秒类似)
1、把问题放在最前,注意在例子中观察(⊙o⊙)哦
- 1> 正常存入秒级别时间的数值数据类型到 MySQL 时 int 就够用(MySQL 是支持无符号的 int,而 mycat 只支持有符号的 int,但是有符号 int 最大为2147483647,即可保存时间到2038-01-19 11:14:07,所有暂时可以把时间保存为 int 类型,完全够用)。
- 2> 当存入毫秒级 13 位(微秒级 16 位)时间的数值数据类型时需要用到 BIGINT,业务代码在进行日期转换为毫秒级的时间戳后需要*1000(*1000000)变为13 位(16 位)的数值数据类型再与数据库中的值进行比较筛选。
- 3> 当存入毫秒级 13 位(微秒级 16 位)时间的数值数据类型时(如毫秒级:1571302437373),后三位(后六位)其实是毫秒(微秒),即原值(去小数点)*1000(*1000000)所得,所以不能直接转换,需要需要把 13 位(16 位)数值(加小数点)先➗1000(➗1000000)再进行转换,或者也可直接截取前十位先转换为正常日期再加上后几位的毫秒或微秒,即转换后时间格式可为 2019-10-17 16:53:57.373,当然你也可以自定义格式。需要注意的一点是,条件筛选时像筛选 2019-10-17 一天的范围就得写为:between 2019-10-17 00:00:00.000 and 2019-10-17 23:59:59.999,当然像 '>'、'<' 等时类似。
- 4> 当使用数值数据类型存储时间是就不能使用像 TIMESTAMP 类型的设置默认时间和设置默认更新时间,需要代码写入 CURRENT_TIMESTAMP,具体方法下面例子中有演示。
- 5> 为什么使用数值数据类型存储时间❓因为索引体量更小, B+树会更加矮胖(什么是 B+树❓);使用数值数据类型存储时间,想转换怎样格式的时间都可以,而且不受时区的约束。
2、建表语句
CREATE TABLE `t_im_message` (
`msg_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`msg` varchar(10) NOT NULL COMMENT '消息内容',
`ctime` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'TIMESTAMP类型创建时间',
`ctime_int` bigint(15) NOT NULL COMMENT '数值数据类型创建时间',
`mtime` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT 'TIMESTAMP类型修改时间',
`mtime_int` bigint(15) NOT NULL COMMENT '数值数据类型修改时间',
PRIMARY KEY (`msg_id`),
KEY `idx_ctime` (`ctime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='测试表';
3、插入测试数据
MySQL [wufei_test]> insert into t_im_message(msg,ctime_int,mtime_int) values('测试数据 01',REPLACE(unix_timestamp(current_timestamp(3)),'.',''),REPLACE(unix_timestamp(current_timestamp(3)),'.',''));
Query OK, 1 row affected (0.01 sec)
MySQL [wufei_test]> insert into t_im_message(msg,ctime_int,mtime_int) values('测试数据 02',REPLACE(unix_timestamp(current_timestamp(3)),'.',''),REPLACE(unix_timestamp(current_timestamp(3)),'.',''));
Query OK, 1 row affected (0.00 sec)
MySQL [wufei_test]> select * from t_im_message;
+--------+-----------------+-------------------------+---------------+-------------------------+---------------+
| msg_id | msg | ctime | ctime_int | mtime | mtime_int |
+--------+-----------------+-------------------------+---------------+-------------------------+---------------+
| 1 | 测试数据 01 | 2019-10-17 16:50:32.987 | 1571302232987 | 2019-10-17 16:50:32.987 | 1571302232987 |
| 2 | 测试数据 02 | 2019-10-17 16:50:44.063 | 1571302244063 | 2019-10-17 16:50:44.063 | 1571302244063 |
+--------+-----------------+-------------------------+---------------+-------------------------+---------------+
2 rows in set (0.00 sec)
4、更新数据
MySQL [wufei_test]> update t_im_message set msg='更新测试数据 02',mtime_int=REPLACE(unix_timestamp(current_timestamp(3)),'.','') where msg_id=2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
MySQL [wufei_test]> select * from t_im_message;
+--------+-----------------------+-------------------------+---------------+-------------------------+---------------+
| msg_id | msg | ctime | ctime_int | mtime | mtime_int |
+--------+-----------------------+-------------------------+---------------+-------------------------+---------------+
| 1 | 测试数据 01 | 2019-10-17 16:50:32.987 | 1571302232987 | 2019-10-17 16:50:32.987 | 1571302232987 |
| 2 | 更新测试数据 02 | 2019-10-17 16:50:44.063 | 1571302244063 | 2019-10-17 16:53:57.373 | 1571302437373 |
+--------+-----------------------+-------------------------+---------------+-------------------------+---------------+
2 rows in set (0.00 sec)
5、数据校验
MySQL [wufei_test]> select * from t_im_message;
+--------+-----------------------+-------------------------+---------------+-------------------------+---------------+
| msg_id | msg | ctime | ctime_int | mtime | mtime_int |
+--------+-----------------------+-------------------------+---------------+-------------------------+---------------+
| 1 | 测试数据 01 | 2019-10-17 16:50:32.987 | 1571302232987 | 2019-10-17 16:50:32.987 | 1571302232987 |
| 2 | 更新测试数据 02 | 2019-10-17 16:50:44.063 | 1571302244063 | 2019-10-17 16:53:57.373 | 1571302437373 |
+--------+-----------------------+-------------------------+---------------+-------------------------+---------------+
2 rows in set (0.00 sec)
MySQL [wufei_test]> select REPLACE(unix_timestamp('2019-10-17 16:53:57.373'),'.','');
+-----------------------------------------------------------+
| REPLACE(unix_timestamp('2019-10-17 16:53:57.373'),'.','') |
+-----------------------------------------------------------+
| 1571302437373 |
+-----------------------------------------------------------+
1 row in set (0.00 sec)