日常业务中经常需要记录时间,如订单生成时间、记录保存时间、更新时间等。如何选择 MySQL 表的时间字段类型呢?
一句话,看业务,具体是看业务是否会跨时区。
MySQL 的日期类型
可以用于记录日期的格式有:
Data type | 实例 | 备注 |
---|---|---|
DATE | '0000-00-00' | 日期(年月日) |
TIME | '00:00:00' | 时间(时分秒) |
DATETIME | '0000-00-00 00:00:00' | 日期+时间(年月日时分秒) |
TIMESTAMP | '0000-00-00 00:00:00' | 时间戳 |
YEAR | 0000 | - |
bigint | 1708589835 | long 类型,保存的也是时间戳 |
varchar | 2024-02-22 16:17:14 | 时间的文本, 只能做记录,不方便排序和计算,不推荐 |
以上类型中,最常见的是 DATETIME、TIMESTAPM 和 BIGINT
日期类型详解
- DATETIME 没有时区概念。保存时,会按照客户端设置的时区时间保存。时间范围是'1000-01-01 00:00:00' 到 '9999-12-31 23:59:59'.
- TIMESTAMP 有时区概念,保存时底层会转换为 UTC 时间,读取时会按照客户端时区展示。时间范围是'1970-01-01 00:00:01' UTC 到'2038-01-19 03:14:07' UTC.
- BIGINT,也就是 Long 类型时间戳,是绝对时间,不区分时区。范围是从 1970-1-1 00:00:00 +0:00 开始,没有上限。
具体解释可以看官方文档: https://dev.mysql.com/doc/refman/8.0/en/datetime.html
新建一张测试表
CREATE TABLE `time_test` (
`datetime` DateTime,
`timestamp` TimeStamp
)ENGINE=InnoDB
查看当前会话的时区
SELECT @@session.time_zone;
+---------------------+
| @@session.time_zone |
+---------------------+
| UTC |
+---------------------+
1 row in set (0.04 sec)
INSERT INTO time_test VALUES(NOW(), NOW());
SELECT * FROM time_test;
+---------------------+---------------------+
| datetime | timestamp |
+---------------------+---------------------+
| 2024-02-22 07:42:20 | 2024-02-22 07:42:20 |
+---------------------+---------------------+
1 row in set (0.03 sec)
# 当前时间是 02-22 15:42
修改会话的时区
set time_zone = "+08:00"
SELECT * FROM time_test;
+---------------------+---------------------+
| datetime | timestamp |
+---------------------+---------------------+
| 2024-02-22 07:42:20 | 2024-02-22 15:42:20 |
+---------------------+---------------------+
1 row in set (0.05 sec)
INSERT INTO time_test VALUES(NOW(), NOW());
SELECT * FROM time_test;
+---------------------+---------------------+
| datetime | timestamp |
+---------------------+---------------------+
| 2024-02-22 07:42:20 | 2024-02-22 15:42:20 |
| 2024-02-22 16:25:05 | 2024-02-22 16:25:05 |
+---------------------+---------------------+
MySQL 时区相关命令
- 查看当前会话时区
SELECT @@session.time_zone; - 设置当前会话时区
SET time_zone = 'Europe/Helsinki';
SET time_zone = "+00:00"; - 数据库全局时区设置
SELECT @@global.time_zone; - 设置全局时区
SET GLOBAL time_zone = '+8:00';
SET GLOBAL time_zone = 'Europe/Helsinki';