MySQL时间字段TIMESTAMP、DATETIME(自动更新、毫秒存储)

本文介绍了MySQL中DATE、TIME、DATETIME和TIMESTAMP四种数据类型,详细阐述了它们的格式、范围以及使用注意事项。TIMESTAMP具有时区转换功能,而DATETIME存储范围更广。在默认值和自动更新方面,两者都可设置为CURRENT_TIMESTAMP。此外,TIMESTAMP能支持毫秒精度,并可通过(n)指定精度。建议在声明字段时明确指定这些特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 数据类型简介

MySQL中关于日期和时间有DATE、TIME、DATETIME、TIMESTAMP这几种数据类型:

  • 1️⃣DATE:储存日期,格式为YYYY-MM-DD,范围1000-01-019999-12-31
  • 2️⃣TIME:储存时间,格式为hhh:mm:ss,范围-838:59:59838:59:59
  • 3️⃣DATETIME:储存日期和时间,格式为YYYY-MM-DD hh:mm:ss,范围1000-01-01 00:00:009999-12-31 23:59:59
  • 4️⃣TIMESTAMP:储存时间戳,格式与DATETIME相同,范围1970-01-01 00:00:012038-01-19 03:14:07

赋值时通过上述格式的字符串赋值即可,还有一些如同NOW()之类的函数也可赋值,但本质可以理解为返回了格式化字符串后赋值的。

其中的TIME可以有缩写,但❌十分不建议❌这样做:

  • 1112将被转化为00:11:12
  • 11:12将被转化为11:12:00

类似地,DATE也可以简写,参考官方文档📖2-Digit Years in Dates

对于后两者(DATETIMETIMESTAMP)很类似,又有所不同:

1️⃣☀️首先能够轻松注意到TIMESTAMP的储存范围比DATETIME小很多,那简单一想:

正经人谁还用TIMESTAMP啊❓

从官方介绍中了解到,TIMESTAMP在存储时会存成UTC时间,在取出时转换为服务器的所在时区时间。因此能够提供时区自动变换的功能,不过看起来不是跨国大鳄🐊也不太用得上这功能……

UTC:协调世界时,又称世界统一时间

2️⃣🌔在未指定默认值时,TIMESTAMPDATETIME的默认值根据是否允许NULL值有区别:

// DATETIME默认允许NULL值,指定不允许NULL时默认值为0
CREATE TABLE t1 (
  dt1 DATETIME ON UPDATE CURRENT_TIMESTAMP,         -- default NULL
  dt2 DATETIME NOT NULL ON UPDATE CURRENT_TIMESTAMP -- default 0
);
// TIMESTAMP默认不允许NULL值,指定允许NULL时默认值为NULL
CREATE TABLE t1 (
  ts1 TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,     -- default 0
  ts2 TIMESTAMP NULL ON UPDATE CURRENT_TIMESTAMP -- default NULL
);

💡建议:这种知识点🔖不建议去记,在声明字段时显式指出☝️即可。

有兴趣可以参考官方文档📖The DATE, DATETIME, and TIMESTAMP Types

2. 方便的处理

2.1 默认值与自动更新

TIMESTAMPDATETIME类型字段,都可以将当前时间戳指定为默认值和/或自动更新值,只需要在创建表格时添加DEFAULT描述和ON UPDATE描述:

// ts和dt将在创建和修改时,被赋值为当前时间
CREATE TABLE t1 (
  ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  dt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

官方文档提到CURRENT_TIMESTAMP有很多同义词,他们效果相同:

  • NOW()
  • CURRENT_TIMESTAMP()
  • LOCALTIME/LOCALTIME()
  • LOCALTIMESTAMP/LOCALTIMESTAMP()

2.2 毫秒及更高精度

可以在声明字段时添加小数点精度,只需要在TIMESTAMP后添加(n)即可,其中0 ≤ n ≤ 6

❗️❗️❗️但要注意:声明时各处的小数精度要一致,如:

CREATE TABLE t1 (
  ts TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),--正确
  dt DATETIME(4) DEFAULT CURRENT_TIMESTAMP(4) ON UPDATE CURRENT_TIMESTAMP(6) -- 错误
);

有兴趣可以参考官方文档📖Fractional Seconds in Time Values


如有错误 ❌ ,欢迎指正 ☝️~

如有收获 🍗,点赞👍/评论💬/收藏⭐️/关注👀~

### 设置 MySQL 长整型时间字段自动更新MySQL 中,`TIMESTAMP` 和 `DATETIME` 是常用的时间类型,但这些都不是长整型(long)。为了实现以毫秒级精度存储并能自动生成和更新的时间戳,可以考虑使用 `BIGINT` 字段来保存 Unix 时间戳的毫秒数。 创建带有自动更新功能的 `BIGINT` 字段可以通过触发器完成。下面是一个例子: #### 创建表结构 ```sql CREATE TABLE example_table ( id INT AUTO_INCREMENT PRIMARY KEY, my_time BIGINT NOT NULL COMMENT 'Unix timestamp in milliseconds', data VARCHAR(255) ); ``` #### 添加插入前触发器 此触发器会在每条记录被插入之前设置 `my_time` 的值为当前时间毫秒级别 Unix 时间戳。 ```sql DELIMITER // CREATE TRIGGER before_insert_example_table BEFORE INSERT ON example_table FOR EACH ROW BEGIN SET NEW.my_time = UNIX_TIMESTAMP(NOW()) * 1000; END// DELIMITER ; ``` #### 更新时也保持最新时间戳 对于更新操作同样适用,这里定义了一个更新后的触发器: ```sql DELIMITER // CREATE TRIGGER after_update_example_table AFTER UPDATE ON example_table FOR EACH ROW BEGIN IF OLD.my_time != NEW.my_time THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Cannot change the value of my_time directly'; END IF; -- Update to current millisecond-level unix timestamp only when other columns are changed. SET NEW.my_time = UNIX_TIMESTAMP(NOW()) * 1000; END// DELIMITER ; ``` 上述方法确保了每当有新纪录加入或已有记录发生变更时,都会将 `my_time` 自动设为最新的毫秒级别的 Unix 时间戳[^1]。 需要注意的是,在实际应用中应当谨慎处理时间戳的选择。考虑到未来可能出现的问题以及可读性和易用性的因素,有时采用 `DATETIME` 或者 `TIMESTAMP` 可能会更加合适[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值