您当前的位置:首页 > 电脑百科 > 数据库 > MYSQL

在 MySQL 中处理时间

时间:2023-05-04 13:41:47  来源:Linux中国  作者:

流行数据库系统 MySQL 的新老用户常常会对数据库处理时间值的方式感到困惑。有时用户不会费心去了解时间值的数据类型。这可能是因为他们觉得本身也没有什么好了解的。日期就是日期,对吧?好吧,并非总是如此。花几分钟时间了解 MySQL 如何存储和显示日期和时间是有益的。学习如何最好地利用数据库表中的时间值可以帮助你成为更好的编码者。

MySQL 时间值类型

当你在 MySQL 中新建表时,选择合适的数据类型(INTFLOATCHAR 等)高效地保存插入到表中的数据。MySQL 为时间值提供了五种数据类型。它们是 DATETIMEDATETIMETIMESTAMP 和 YEAR

MySQL 使用 ISO 8601 格式来存储以下格式的值(LCTT 译注:国际标准 ISO 8601,是国际标准化组织的日期和时间的表示方法,全称为《数据存储和交换形式·信息交换·日期和时间的表示方法》):

  • DATEYYYY-MM-DD
  • TIMEHH:MM:SS
  • TIMESTAMPYYYY-MM-DD HH:MM:SS
  • YEARYYYY

DATETIME 与 TIMESTAMP 的比较

你可能已经注意到 日期时间DATETIME 和 时间戳TIMESTAMP

首先,可以使用的日期范围不同。DATETIME 可以保存 1000-01-01 00:00:00 和 9999-12-31 23:59:59 之间的日期,而 TIMESTAMP 的范围更有限,从 1970-01-01 00:00:01 到 2038-01-19 03:14:07 UTC。

其次,虽然两种数据类型都允许你 自动初始化auto_initialize 或 自动更新auto_update 它们各自的值(分别用 DEFAULT CURRENT_TIMESTAMP 和 ON UPDATE CURRENT_TIMESTAMP),但在 5.6.5 版本之前,对 DATETIME 值不能这样操作。如果你要用 DATETIME,你可以使用 CURRENT_TIMESTAMP 的 MySQL 同义词之一,例如 NOW() 或 LOCALTIME()

如果你对一个 DATETIME 值使用 ON UPDATE CURENT_TIMESTAMP(或其同义词之一),但没有使用 DEFAULT CURRENT_TIMESTAMP 子句,那么这个列的默认值为 NULL。除非你在表的定义中包含 NOT NULL,在这种情况下,它默认为 0。

另一件需要记住的重要事情是,尽管通常情况下,除非你声明一个默认值,否则 DATETIME 和 TIMESTAMP 列都没有一个默认值,但这个规则有一个例外。如果没有指定 DEFAULT CURRENT_TIMESTAMP 和 ON UPDATE CURRENT_TIMESTAMP 这两个子句,并且禁用 explicit_defaults_for_timestamp 这个变量,那么你表中的第一个 TIMESTAMP 列将被隐式创建。

要检查这个变量的状态,请运行:

mysql> show variables like 'explicit_default%';

如果你想打开或关闭它,运行这段代码(用 0 表示关闭,用 1 表示打开):

mysql> set explicit_defaults_for_timestamp = 0;

TIME

MySQL 的 时间TIME

首先要注意的是,虽然 TIME 经常被认为是一天中的时间,但它实际上是经过的时间。换句话说,它可以是一个负值,或者可以大于 23:59:59。在 MySQL 中,一个 TIME 值的范围可以是 -838:59:59 到 838:59:59。

另外,如果你缩写一个时间值,MySQL 会因你是否使用冒号作出不同解释。例如,10:34 这个值被 MySQL 看作是 10:34:00。也就是说,十点过后的 34 分钟。但是,如果你不使用冒号写作 1034,MySQL 将其视为 00:10:34,意思是 10 分钟 34 秒。

最后,你应该知道 TIME 值(以及 DATETIME 和 TIMESTAMP 字段的时间部分)从 5.6.4 版本开始,可以取一个小数部分。要使用它,请在数据类型定义的结尾处添加一个整数(最大值为 6)的圆括号。

time_column TIME(2)

时区

时区变化不仅在现实世界中产生混乱和疲劳,而且也会在数据库系统中制造麻烦。地球被划分为 24 个独立的时区,通常每隔 15 度经度就会发生变化。我说通常是因为一些国家行事方式不同。例如中国只在一个时区运作,而不是预期的五个时区。

你如何处理处于不同时区的数据库系统的用户就成了一个问题。幸运的是,MySQL 并没有使这个问题变得太困难。

要检查你的会话时区,请运行:

mysql> select @@session.time_zone;

如果结果显示 System,这意味着它正在使用你的 my.cnf 配置文件中设置的时区。如果你在本地计算机上运行你的 MySQL 服务器,这可能就是你会得到的,你不需要做任何改变。

如果你想改变你的会话的时区,请运行如下命令:

mysql> set time_zone = '-05:00';

这将你的时区设置为 美国/东部US/Eastern,比 协调世界时UTC

获得一周的日期

为了跟上本教程后面部分的代码,你应该在你的系统中创建一个带有日期值类型的表。比如:

mysql> create table test
( row_id smallint not null auto_increment primary key,
the_date date not null);

然后使用 ISO 8601 格式在表中插入一些随机日期,如

mysql> insert into test (the_date) VALUES ('2022-01-05');

我在我的 test 表中插入了四行日期值,你插入多少行都可以。

有时你可能想知道某一天是星期几。MySQL 给了你几种实现方法。

第一种,也是最显而易见的方法,是使用 DAYNAME() 函数。如下示例表所展示,DAYNAME() 函数可以告诉你每个日期是星期几:

mysql> SELECT the_date, DAYNAME(the_date) FROM test;
+------------+-------------------------------+
| the_date   | DAYNAME(the_date)             |
+------------+-------------------------------+
| 2021-11-02 | Tuesday                       |
| 2022-01-05 | Wednesday                     |
| 2022-05-03 | Tuesday                       |
| 2023-01-13 | Friday                        |
+------------+-------------------------------+
4 rows in set (0.00 sec)

另外两种获取星期几的方法是返回整数值,而不是星期几的名称,分别是 WEEKDAY() 和 DAYOFWEEK()。他们都返回数字,却又各不相同。WEEKDAY() 函数返回从 0 到 6 的数字,其中 0 代表星期一,6 代表星期日。而 DAYOFWEEK() 则返回从 1 到 7 的数字,其中 1 代表星期日,7 代表星期六。

mysql> SELECT the_date, DAYNAME(the_date),
WEEKDAY(the_date), DAYOFWEEK(the_date) FROM test;
+------------+------------------+------------------+--------------------+
| the_date   | DAYNAME(the_date)| WEEKDAY(the_date)| DAYOFWEEK(the_date)|
| 2021-11-02 | Tuesday          | 1                | 3                  |
| 2022-01-05 | Wednesday        | 2                | 4                  |
| 2022-05-03 | Tuesday          | 1                | 3                  |
| 2023-01-13 | Friday           | 4                | 6                  |
+------------+------------------+------------------+--------------------+
4 rows in set (0.00 sec)

当你只想获取日期的一部分时

有时你可能在 MySQL 表中存储了一个日期,但是你只想获取日期的一部分。这并不是问题。

MySQL 中有几个顾名思义的函数,可以轻松获取日期对象的特定部分。以下是一些示例:

mysql> SELECT the_date, YEAR(the_date), MONTHNAME(the_date), 
DAYOFMONTH(the_date) FROM test ;
+-----------+---------------+-------------------+---------------------+
| the_date  | YEAR(the_date)|MONTHNAME(the_date)| DAYOFMONTH(the_date)|
+-----------+---------------+-------------------+---------------------+
| 2021-11-02| 2021          | November          | 2                   |
| 2022-01-05| 2022          | January           | 5                   |
| 2022-05-03| 2022          | May               | 3                   |
| 2023-01-13| 2023          | January           | 13                  |
+-----------+---------------+-------------------+---------------------+
4 rows in set (0.00 sec)

MySQL 也允许你使用 EXTRACT() 函数来获取日期的一部分。你提供给函数的参数是一个单位说明符(确保是单数形式)、FROM 和列名。因此,为了从我们的 test 表中仅获取年份,你可以写:

mysql> SELECT EXTRACT(YEAR FROM the_date) FROM test;
+----------------------------------------------+
| EXTRACT(YEAR FROM the_date)                  |
+----------------------------------------------+
| 2021                                         |
| 2022                                         |
| 2022                                         |
| 2023                                         |
+----------------------------------------------+
4 rows in set (0.01 sec)

插入和读取不同格式的日期

正如之前提到的,MySQL 使用 ISO 8601 格式存储日期和时间值。但是如果你想以另一种方式存储日期和时间值,例如 MM-DD-YYYY 格式,怎么办?首先,不要尝试这样做。MySQL 以 8601 格式存储日期和时间,就是这样。不要尝试更改它。但是,这并不意味着你必须在将数据输入到数据库之前将数据转换为特定的格式,或者你不能以任何你想要的格式展示数据。

如果你想要将非 ISO 的格式的日期输入到表中,你可以使用 STR_TO_DATE() 函数。第一个参数是你想要存储在数据库中的日期的字符串值。第二个参数是格式化字符串,它让 MySQL 知道日期的组织方式。让我们看一个简单的例子,然后我将更深入地研究这个看起来很奇怪的格式化字符串是什么。

mysql> insert into test (the_date) values (str_to_date('January 13, 2023','%M %d, %Y'));
Query OK, 1 row affected (0.00 sec)

你将格式化字符串放在引号中,并在每个特殊字符前加上百分号。上面代码中的格式序列告诉 MySQL 我的日期由一个完整的月份名称 %M,后跟一个两位数的日期%d,然后是一个逗号,最后由一个四位数的年份 %Y 组成。请注意,大写很重要。

一些其他常用的格式化字符串字符是:

  • %b 缩写月份的名称(例如: Jan
  • %c 数字月份(例如: 1)
  • %W 星期名称(例如: `Saturday)
  • %a 星期名称的缩写(例如: Sat
  • %T 24 小时制的时间(例如: 22:01:22
  • %r 带 AM/PM 的 12 小时制的时间(例如: 10:01:22 PM
  • %y 两位数的年份(例如: 23)

请注意,对于两位数年份 %y,年份范围是 1970 到 2069。因此,从 70 到 99 的数字被假定为 20 世纪,而从 00 到 69 的数字被假定为 21 世纪。

如果你有一个日期存储在你的数据库中,你想用不同的格式显示它,你可以使用这个 DATE_FORMAT() 函数:

mysql> SELECT DATE_FORMAT(the_date, '%W, %b. %d, %y') FROM test;
+-----------------------------------------+
| DATE_FORMAT(the_date, '%W, %b. %d, %y') |
+-----------------------------------------+
| Tuesday, Nov. 02, 21                    |
| Wednesday, Jan. 05, 22                  |
| Tuesday, May. 03, 22                    |
| Friday, Jan. 13, 23                     |
+-----------------------------------------+
4 rows in set (0.00 sec)

总结

本教程应该为你提供了一个关于 MySQL 中的日期和时间值的有用的概述。我希望本文教会了您一些新知识,使您能够更好地控制和理解 MySQL 数据库如何处理时间值。

(题图:MJ/76b6481a-a271-4e81-bc17-dd7fbe08a240)



Tags:MySQL   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
MySQL 核心模块揭秘
server 层会创建一个 SAVEPOINT 对象,用于存放 savepoint 信息。binlog 会把 binlog offset 写入 server 层为它分配的一块 8 字节的内存里。 InnoDB 会维护自己的 savepoint...【详细内容】
2024-04-03  Search: MySQL  点击:(6)  评论:(0)  加入收藏
MySQL 核心模块揭秘,你看明白了吗?
为了提升分配 undo 段的效率,事务提交过程中,InnoDB 会缓存一些 undo 段。只要同时满足两个条件,insert undo 段或 update undo 段就能被缓存。1. 关于缓存 undo 段为了提升分...【详细内容】
2024-03-27  Search: MySQL  点击:(11)  评论:(0)  加入收藏
MySQL:BUG导致DDL语句无谓的索引重建
对于5.7.23之前的版本在评估类似DDL操作的时候需要谨慎,可能评估为瞬间操作,但是实际上线的时候跑了很久,这个就容易导致超过维护窗口,甚至更大的故障。一、问题模拟使用5.7.22...【详细内容】
2024-03-26  Search: MySQL  点击:(10)  评论:(0)  加入收藏
从 MySQL 到 ByteHouse,抖音精准推荐存储架构重构解读
ByteHouse是一款OLAP引擎,具备查询效率高的特点,在硬件需求上相对较低,且具有良好的水平扩展性,如果数据量进一步增长,可以通过增加服务器数量来提升处理能力。本文将从兴趣圈层...【详细内容】
2024-03-22  Search: MySQL  点击:(24)  评论:(0)  加入收藏
MySQL自增主键一定是连续的吗?
测试环境:MySQL版本:8.0数据库表:T (主键id,唯一索引c,普通字段d)如果你的业务设计依赖于自增主键的连续性,这个设计假设自增主键是连续的。但实际上,这样的假设是错的,因为自增主键不...【详细内容】
2024-03-10  Search: MySQL  点击:(6)  评论:(0)  加入收藏
准线上事故之MySQL优化器索引选错
1 背景最近组里来了许多新的小伙伴,大家在一起聊聊技术,有小兄弟提到了MySQL的优化器的内部策略,想起了之前在公司出现的一个线上问题,今天借着这个机会,在这里分享下过程和结论...【详细内容】
2024-03-07  Search: MySQL  点击:(28)  评论:(0)  加入收藏
MySQL数据恢复,你会吗?
今天分享一下binlog2sql,它是一款比较常用的数据恢复工具,可以通过它从MySQL binlog解析出你要的SQL,并根据不同选项,可以得到原始SQL、回滚SQL、去除主键的INSERT SQL等。主要...【详细内容】
2024-02-22  Search: MySQL  点击:(45)  评论:(0)  加入收藏
如何在MySQL中实现数据的版本管理和回滚操作?
实现数据的版本管理和回滚操作在MySQL中可以通过以下几种方式实现,包括使用事务、备份恢复、日志和版本控制工具等。下面将详细介绍这些方法。1.使用事务:MySQL支持事务操作,可...【详细内容】
2024-02-20  Search: MySQL  点击:(53)  评论:(0)  加入收藏
为什么高性能场景选用Postgres SQL 而不是 MySQL
一、 数据库简介 TLDR;1.1 MySQL MySQL声称自己是最流行的开源数据库,它属于最流行的RDBMS (Relational Database Management System,关系数据库管理系统)应用软件之一。LAMP...【详细内容】
2024-02-19  Search: MySQL  点击:(38)  评论:(0)  加入收藏
MySQL数据库如何生成分组排序的序号
经常进行数据分析的小伙伴经常会需要生成序号或进行数据分组排序并生成序号。在MySQL8.0中可以使用窗口函数来实现,可以参考历史文章有了这些函数,统计分析事半功倍进行了解。...【详细内容】
2024-01-30  Search: MySQL  点击:(54)  评论:(0)  加入收藏
▌简易百科推荐
MySQL 核心模块揭秘
server 层会创建一个 SAVEPOINT 对象,用于存放 savepoint 信息。binlog 会把 binlog offset 写入 server 层为它分配的一块 8 字节的内存里。 InnoDB 会维护自己的 savepoint...【详细内容】
2024-04-03  爱可生开源社区    Tags:MySQL   点击:(6)  评论:(0)  加入收藏
MySQL 核心模块揭秘,你看明白了吗?
为了提升分配 undo 段的效率,事务提交过程中,InnoDB 会缓存一些 undo 段。只要同时满足两个条件,insert undo 段或 update undo 段就能被缓存。1. 关于缓存 undo 段为了提升分...【详细内容】
2024-03-27  爱可生开源社区  微信公众号  Tags:MySQL   点击:(11)  评论:(0)  加入收藏
MySQL:BUG导致DDL语句无谓的索引重建
对于5.7.23之前的版本在评估类似DDL操作的时候需要谨慎,可能评估为瞬间操作,但是实际上线的时候跑了很久,这个就容易导致超过维护窗口,甚至更大的故障。一、问题模拟使用5.7.22...【详细内容】
2024-03-26  MySQL学习  微信公众号  Tags:MySQL   点击:(10)  评论:(0)  加入收藏
从 MySQL 到 ByteHouse,抖音精准推荐存储架构重构解读
ByteHouse是一款OLAP引擎,具备查询效率高的特点,在硬件需求上相对较低,且具有良好的水平扩展性,如果数据量进一步增长,可以通过增加服务器数量来提升处理能力。本文将从兴趣圈层...【详细内容】
2024-03-22  字节跳动技术团队    Tags:ByteHouse   点击:(24)  评论:(0)  加入收藏
MySQL自增主键一定是连续的吗?
测试环境:MySQL版本:8.0数据库表:T (主键id,唯一索引c,普通字段d)如果你的业务设计依赖于自增主键的连续性,这个设计假设自增主键是连续的。但实际上,这样的假设是错的,因为自增主键不...【详细内容】
2024-03-10    dbaplus社群  Tags:MySQL   点击:(6)  评论:(0)  加入收藏
准线上事故之MySQL优化器索引选错
1 背景最近组里来了许多新的小伙伴,大家在一起聊聊技术,有小兄弟提到了MySQL的优化器的内部策略,想起了之前在公司出现的一个线上问题,今天借着这个机会,在这里分享下过程和结论...【详细内容】
2024-03-07  转转技术  微信公众号  Tags:MySQL   点击:(28)  评论:(0)  加入收藏
MySQL数据恢复,你会吗?
今天分享一下binlog2sql,它是一款比较常用的数据恢复工具,可以通过它从MySQL binlog解析出你要的SQL,并根据不同选项,可以得到原始SQL、回滚SQL、去除主键的INSERT SQL等。主要...【详细内容】
2024-02-22  数据库干货铺  微信公众号  Tags:MySQL   点击:(45)  评论:(0)  加入收藏
如何在MySQL中实现数据的版本管理和回滚操作?
实现数据的版本管理和回滚操作在MySQL中可以通过以下几种方式实现,包括使用事务、备份恢复、日志和版本控制工具等。下面将详细介绍这些方法。1.使用事务:MySQL支持事务操作,可...【详细内容】
2024-02-20  编程技术汇    Tags:MySQL   点击:(53)  评论:(0)  加入收藏
MySQL数据库如何生成分组排序的序号
经常进行数据分析的小伙伴经常会需要生成序号或进行数据分组排序并生成序号。在MySQL8.0中可以使用窗口函数来实现,可以参考历史文章有了这些函数,统计分析事半功倍进行了解。...【详细内容】
2024-01-30  数据库干货铺  微信公众号  Tags:MySQL   点击:(54)  评论:(0)  加入收藏
mysql索引失效的场景
MySQL中索引失效是指数据库查询时无法有效利用索引,这可能导致查询性能显著下降。以下是一些常见的MySQL索引失效的场景:1.使用非前导列进行查询: 假设有一个复合索引 (A, B)。...【详细内容】
2024-01-15  小王爱编程  今日头条  Tags:mysql索引   点击:(85)  评论:(0)  加入收藏
站内最新
站内热门
站内头条