像编程语言一样,MySQL同样也提供了一部分内置函数供用户在SQL中进行调用。这些内置函数能简单处理一部分数据,避免我们在不同的用户层语言中进行逻辑编写。

1.日期函数

函数作用
current_date()当前日期
current_time()当前时间
current_timestamp()当前日期和时间
now()当前日期和时间(同上)
unix_timestamp()当前时间戳数字
date(datetime)返回datetime参数中的日期部分
date_add(date,interval d_value_type)在date中添加日期或时间,interval后的参数可以是year/month/day/hour/mintue/second
date_sub(date,interval d_value_type)在date中减去日期或时间,interval后的参数可以是year/month/day/hour/mintue/second
datediff(date1,date2)计算两个日期的时间差,单位为天
date_format(date,format_string)根据format_string字符串来格式化时间显示
year(date)获取日期中的年份
month(date)获取日期中的月份
day(date)获取日期中的天
str_to_date(string,format_string)字符串转时间

下面挨个做个演示

1.1 获取日期和时间

获取时间分为获取当前日期,获取当前时间,和获取当前日期+时间;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
MariaDB [(none)]> select current_time();
+----------------+
| current_time() |
+----------------+
| 14:27:49 |
+----------------+
1 row in set (0.000 sec)

MariaDB [(none)]> select now();
+---------------------+
| now() |
+---------------------+
| 2024-01-30 14:27:53 |
+---------------------+
1 row in set (0.000 sec)

MariaDB [(none)]> select current_date();
+----------------+
| current_date() |
+----------------+
| 2024-01-30 |
+----------------+
1 row in set (0.000 sec)

MariaDB [(none)]> select current_timestamp();
+---------------------+
| current_timestamp() |
+---------------------+
| 2024-01-30 14:30:39 |
+---------------------+
1 row in set (0.000 sec)

经过测试可以发现,在MySQL中,current_timestamp()函数和now()函数的效果等效。

只有UNIX_TIMESTAMP()函数返回的才是时间戳的数字

1
2
3
4
5
6
7
MariaDB [(none)]> SELECT UNIX_TIMESTAMP();
+------------------+
| UNIX_TIMESTAMP() |
+------------------+
| 1706596346 |
+------------------+
1 row in set (0.000 sec)

image-20240130143435696

1.2 获取时间的部分值

使用YEAR\MONTH\DAY函数从一个时间中提取日期的部分信息

1
2
3
SELECT YEAR(NOW()) AS current_year;
SELECT MONTH(NOW()) AS current_month;
SELECT DAY(NOW()) AS current_day;

执行效果如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
MariaDB [(none)]> SELECT YEAR(NOW()) AS current_year;
+--------------+
| current_year |
+--------------+
| 2024 |
+--------------+
1 row in set (0.001 sec)

MariaDB [(none)]> SELECT MONTH(NOW()) AS current_month;
+---------------+
| current_month |
+---------------+
| 1 |
+---------------+
1 row in set (0.000 sec)

MariaDB [(none)]> SELECT DAY(NOW()) AS current_day;
+-------------+
| current_day |
+-------------+
| 30 |
+-------------+
1 row in set (0.000 sec)

1.3 时间运算

MySQL中时间可以直接用加减进行运算,时间列和时间函数返回的时间之间可以通过大于小于来比较大小;

1
2
3
4
5
6
7
MariaDB [(none)]> SELECT NOW() + INTERVAL 1 DAY;
+------------------------+
| NOW() + INTERVAL 1 DAY |
+------------------------+
| 2024-01-31 14:49:57 |
+------------------------+
1 row in set (0.000 sec)

在大学数据库的考试中一般会给出一张表,存了学生的出生日期,让你筛选出年龄小于20岁的学生,此时就需要进行年份的提取和时间计算

1
2
3
-- 假设学生表中是id,name,birth三个字段
select id,name from student
where (year(now()) - year(birth)) < 20;

下面演示表格中提到的date_add/date_sub运算函数的用法

1
2
3
4
5
6
7
8
9
10
11
12
-- 在日期的基础上加上时间
select date_add('2024-1-1',interval 2 month);
-- 在日期的基础上减去时间
select date_sub('2023-10-1', interval 2 day);

-- 第二个参数可选的时间间隔
INTERVAL 1 YEAR
INTERVAL 1 MONTH
INTERVAL 1 DAY
INTERVAL 1 HOUR
INTERVAL 1 MINUTE
INTERVAL 1 SECOND

效果如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
MariaDB [(none)]> select date_sub('2023-10-1', interval 2 day);
+---------------------------------------+
| date_sub('2023-10-1', interval 2 day) |
+---------------------------------------+
| 2023-09-29 |
+---------------------------------------+
1 row in set (0.000 sec)

MariaDB [(none)]> select date_add('2024-1-1',interval 2 month);
+---------------------------------------+
| date_add('2024-1-1',interval 2 month) |
+---------------------------------------+
| 2024-03-01 |
+---------------------------------------+
1 row in set (0.000 sec)

另外,MySQL中是允许日期中出现前导0的,依旧可以被正常识别

1
2
3
4
5
6
7
MariaDB [(none)]> select date_sub('2023-01-01', interval 2 day);
+----------------------------------------+
| date_sub('2023-01-01', interval 2 day) |
+----------------------------------------+
| 2022-12-30 |
+----------------------------------------+
1 row in set (0.000 sec)

使用datediff函数计算两个日期的差值(日期要用单引号传入)

1
2
3
4
5
6
7
MariaDB [(none)]> SELECT DATEDIFF('2022-01-30', '2022-01-15');
+--------------------------------------+
| DATEDIFF('2022-01-30', '2022-01-15') |
+--------------------------------------+
| 15 |
+--------------------------------------+
1 row in set (0.000 sec)

具体例子:在msg表中查询两分钟内发布的消息,可以用date_add函数来实现。

1
2
select * from msg 
where date_add(sendtime, interval 2 minute) > now();

1.4 日期格式化

使用date_format函数将时间格式化输出

1
select DATE_FORMAT(now(),'%Y-%m-%d %H:%i:%s');

在这个格式化字符串中,你可以把一些值给写死,比如将分钟和秒写死为0点0分;

1
select DATE_FORMAT(now(),'%Y-%m-%d %H:00:00');

最终效果如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
MariaDB [(none)]> select DATE_FORMAT(now(),'%Y-%m-%d %H:%i:%s');
+----------------------------------------+
| DATE_FORMAT(now(),'%Y-%m-%d %H:%i:%s') |
+----------------------------------------+
| 2024-01-30 14:59:33 |
+----------------------------------------+
1 row in set (0.000 sec)

MariaDB [(none)]> select DATE_FORMAT(now(),'%Y-%m-%d %H:00:00');
+----------------------------------------+
| DATE_FORMAT(now(),'%Y-%m-%d %H:00:00') |
+----------------------------------------+
| 2024-01-30 14:00:00 |
+----------------------------------------+
1 row in set (0.000 sec)

年份Y可以为小y,此时只显示年份的后二位

1
2
3
4
5
6
7
MariaDB [(none)]> select DATE_FORMAT(now(),'%y-%m-%d %H:%i:%s');
+----------------------------------------+
| DATE_FORMAT(now(),'%y-%m-%d %H:%i:%s') |
+----------------------------------------+
| 24-01-30 15:00:23 |
+----------------------------------------+
1 row in set (0.000 sec)

1.5 字符串转时间

str_to_date函数可以将给定的时间字符串和给定的字符串时间格式,转换为一个datetime类型

1
select str_to_date('2024-01-02 20:37:14', '%Y-%m-%d %H:%i:%s');

效果如下

1
2
3
4
5
6
7
MariaDB [(none)]> select str_to_date('2024-01-02 20:37:14', '%Y-%m-%d %H:%i:%s');
+---------------------------------------------------------+
| str_to_date('2024-01-02 20:37:14', '%Y-%m-%d %H:%i:%s') |
+---------------------------------------------------------+
| 2024-01-02 20:37:14 |
+---------------------------------------------------------+
1 row in set (0.000 sec)

如果你给定的格式化字符串和时间字符串不符合,则无法成功转换,结果为NULL

1
2
3
4
5
6
7
MariaDB [(none)]> select str_to_date('2024-01-02 20:37:14', '%y-%m-%d %H:%i:%s');
+---------------------------------------------------------+
| str_to_date('2024-01-02 20:37:14', '%y-%m-%d %H:%i:%s') |
+---------------------------------------------------------+
| NULL |
+---------------------------------------------------------+
1 row in set, 1 warning (0.000 sec)

1.6 其他参考函数

以下是比较全的MySQL日期函数,可供参考

点我查看

原文链接:MySQL之日期时间处理函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
-- MySQL日期时间处理函数
-- 当前日期:2017-05-12(突然发现今天512,是不是会拉防空警报)
SELECT NOW() FROM DUAL;-- 当前日期时间:2017-05-12 11:41:47
-- 在MySQL里也存在和Oracle里类似的dual虚拟表:官方声明纯粹是为了满足select ... from...这一习惯问题,mysql会忽略对该表的引用。
-- 那么MySQL中就不用DUAL了吧。
SELECT NOW();-- 当前日期时间:2017-05-12 11:41:55
-- 除了 now() 函数能获得当前的日期时间外,MySQL 中还有下面的函数:
SELECT CURRENT_TIMESTAMP();-- 2017-05-15 10:19:31
SELECT CURRENT_TIMESTAMP;-- 2017-05-15 10:19:51
SELECT LOCALTIME();-- 2017-05-15 10:20:00
SELECT LOCALTIME;-- 2017-05-15 10:20:10
SELECT LOCALTIMESTAMP();-- 2017-05-15 10:20:21(v4.0.6)
SELECT LOCALTIMESTAMP;-- 2017-05-15 10:20:30(v4.0.6)
-- 这些日期时间函数,都等同于 now()。鉴于 now() 函数简短易记,建议总是使用 now()来替代上面列出的函数。

SELECT SYSDATE();-- 当前日期时间:2017-05-12 11:42:03
-- sysdate() 日期时间函数跟 now() 类似,
-- 不同之处在于:now() 在执行开始时值就得到了;sysdate() 在函数执行时动态得到值。
-- 看下面的例子就明白了:
SELECT NOW(), SLEEP(3), NOW();
SELECT SYSDATE(), SLEEP(3), SYSDATE();


SELECT CURDATE();-- 当前日期:2017-05-12
SELECT CURRENT_DATE();-- 当前日期:等同于 CURDATE()
SELECT CURRENT_DATE;-- 当前日期:等同于 CURDATE()

SELECT CURTIME();-- 当前时间:11:42:47
SELECT CURRENT_TIME();-- 当前时间:等同于 CURTIME()
SELECT CURRENT_TIME;-- 当前时间:等同于 CURTIME()

-- 获得当前 UTC 日期时间函数
SELECT UTC_TIMESTAMP(), UTC_DATE(), UTC_TIME()
-- MySQL 获得当前时间戳函数:current_timestamp, current_timestamp()
SELECT CURRENT_TIMESTAMP, CURRENT_TIMESTAMP();-- 2017-05-15 10:32:21 | 2017-05-15 10:32:21


-- MySQL 日期时间 Extract(选取) 函数
SET @dt = '2017-05-15 10:37:14.123456';
SELECT DATE(@dt);-- 获取日期:2017-05-15
SELECT TIME('2017-05-15 10:37:14.123456');-- 获取时间:10:37:14.123456
SELECT YEAR('2017-05-15 10:37:14.123456');-- 获取年份
SELECT MONTH('2017-05-15 10:37:14.123456');-- 获取月份
SELECT DAY('2017-05-15 10:37:14.123456');-- 获取日
SELECT HOUR('2017-05-15 10:37:14.123456');-- 获取时
SELECT MINUTE('2017-05-15 10:37:14.123456');-- 获取分
SELECT SECOND('2017-05-15 10:37:14.123456');-- 获取秒
SELECT MICROSECOND('2017-05-15 10:37:14.123456');-- 获取毫秒
SELECT QUARTER('2017-05-15 10:37:14.123456');-- 获取季度
SELECT WEEK('2017-05-15 10:37:14.123456');-- 20 (获取周)
SELECT WEEK('2017-05-15 10:37:14.123456', 7);-- ****** 测试此函数在MySQL5.6下无效
SELECT WEEKOFYEAR('2017-05-15 10:37:14.123456');-- 同week()
SELECT DAYOFYEAR('2017-05-15 10:37:14.123456');-- 135 (日期在年度中第几天)
SELECT DAYOFMONTH('2017-05-15 10:37:14.123456');-- 5 (日期在月度中第几天)
SELECT DAYOFWEEK('2017-05-15 10:37:14.123456');-- 2 (日期在周中第几天;周日为第一天)
SELECT WEEKDAY('2017-05-15 10:37:14.123456');-- 0
SELECT WEEKDAY('2017-05-21 10:37:14.123456');-- 6(与dayofweek()都表示日期在周的第几天,只是参考标准不同,weekday()周一为第0天,周日为第6天)
SELECT YEARWEEK('2017-05-15 10:37:14.123456');-- 201720(年和周)

SELECT EXTRACT(YEAR FROM '2017-05-15 10:37:14.123456');
SELECT EXTRACT(MONTH FROM '2017-05-15 10:37:14.123456');
SELECT EXTRACT(DAY FROM '2017-05-15 10:37:14.123456');
SELECT EXTRACT(HOUR FROM '2017-05-15 10:37:14.123456');
SELECT EXTRACT(MINUTE FROM '2017-05-15 10:37:14.123456');
SELECT EXTRACT(SECOND FROM '2017-05-15 10:37:14.123456');
SELECT EXTRACT(MICROSECOND FROM '2017-05-15 10:37:14.123456');
SELECT EXTRACT(QUARTER FROM '2017-05-15 10:37:14.123456');
SELECT EXTRACT(WEEK FROM '2017-05-15 10:37:14.123456');
SELECT EXTRACT(YEAR_MONTH FROM '2017-05-15 10:37:14.123456');
SELECT EXTRACT(DAY_HOUR FROM '2017-05-15 10:37:14.123456');
SELECT EXTRACT(DAY_MINUTE FROM '2017-05-15 10:37:14.123456');-- 151037(日时分)
SELECT EXTRACT(DAY_SECOND FROM '2017-05-15 10:37:14.123456');-- 15103714(日时分秒)
SELECT EXTRACT(DAY_MICROSECOND FROM '2017-05-15 10:37:14.123456');-- 15103714123456(日时分秒毫秒)
SELECT EXTRACT(HOUR_MINUTE FROM '2017-05-15 10:37:14.123456');-- 1037(时分)
SELECT EXTRACT(HOUR_SECOND FROM '2017-05-15 10:37:14.123456');-- 103714(时分秒)
SELECT EXTRACT(HOUR_MICROSECOND FROM '2017-05-15 10:37:14.123456');-- 103714123456(日时分秒毫秒)
SELECT EXTRACT(MINUTE_SECOND FROM '2017-05-15 10:37:14.123456');-- 3714(分秒)
SELECT EXTRACT(MINUTE_MICROSECOND FROM '2017-05-15 10:37:14.123456');-- 3714123456(分秒毫秒)
SELECT EXTRACT(SECOND_MICROSECOND FROM '2017-05-15 10:37:14.123456');-- 14123456(秒毫秒)
-- MySQL Extract() 函数除了没有date(),time() 的功能外,其他功能一应具全。
-- 并且还具有选取‘day_microsecond' 等功能。
-- 注意这里不是只选取 day 和 microsecond,而是从日期的 day 部分一直选取到 microsecond 部分。


SELECT DAYNAME('2017-05-15 10:37:14.123456');-- Monday(返回英文星期)
SELECT MONTHNAME('2017-05-15 10:37:14.123456');-- May(返回英文月份)
SELECT LAST_DAY('2016-02-01');-- 2016-02-29 (返回月份中最后一天)
SELECT LAST_DAY('2016-05-01');-- 2016-05-31

-- DATE_ADD(date,INTERVAL expr type) 从日期加上指定的时间间隔
-- type参数可参考:http://www.w3school.com.cn/sql/func_date_sub.asp
SELECT DATE_ADD('2017-05-15 10:37:14.123456',INTERVAL 1 YEAR);-- 表示:2018-05-15 10:37:14.123456
SELECT DATE_ADD('2017-05-15 10:37:14.123456',INTERVAL 1 QUARTER);-- 表示:2017-08-15 10:37:14.123456
SELECT DATE_ADD('2017-05-15 10:37:14.123456',INTERVAL 1 MONTH);-- 表示:2017-06-15 10:37:14.123456
SELECT DATE_ADD('2017-05-15 10:37:14.123456',INTERVAL 1 WEEK);-- 表示:2017-05-22 10:37:14.123456
SELECT DATE_ADD('2017-05-15 10:37:14.123456',INTERVAL 1 DAY);-- 表示:2017-05-16 10:37:14.123456
SELECT DATE_ADD('2017-05-15 10:37:14.123456',INTERVAL 1 HOUR);-- 表示:2017-05-15 11:37:14.123456
SELECT DATE_ADD('2017-05-15 10:37:14.123456',INTERVAL 1 MINUTE);-- 表示:2017-05-15 10:38:14.123456
SELECT DATE_ADD('2017-05-15 10:37:14.123456',INTERVAL 1 SECOND);-- 表示:2017-05-15 10:37:15.123456
SELECT DATE_ADD('2017-05-15 10:37:14.123456',INTERVAL 1 MICROSECOND);-- 表示:2017-05-15 10:37:14.123457


-- DATE_SUB(date,INTERVAL expr type) 从日期减去指定的时间间隔
SELECT DATE_SUB('2017-05-15 10:37:14.123456',INTERVAL 1 YEAR);-- 表示:2016-05-15 10:37:14.123456
SELECT DATE_SUB('2017-05-15 10:37:14.123456',INTERVAL 1 QUARTER);-- 表示:2017-02-15 10:37:14.123456
SELECT DATE_SUB('2017-05-15 10:37:14.123456',INTERVAL 1 MONTH);-- 表示:2017-04-15 10:37:14.123456
SELECT DATE_SUB('2017-05-15 10:37:14.123456',INTERVAL 1 WEEK);-- 表示:2017-05-08 10:37:14.123456
SELECT DATE_SUB('2017-05-15 10:37:14.123456',INTERVAL 1 DAY);-- 表示:2017-05-14 10:37:14.123456
SELECT DATE_SUB('2017-05-15 10:37:14.123456',INTERVAL 1 HOUR);-- 表示:2017-05-15 09:37:14.123456
SELECT DATE_SUB('2017-05-15 10:37:14.123456',INTERVAL 1 MINUTE);-- 表示:2017-05-15 10:36:14.123456
SELECT DATE_SUB('2017-05-15 10:37:14.123456',INTERVAL 1 SECOND);-- 表示:2017-05-15 10:37:13.123456
SELECT DATE_SUB('2017-05-15 10:37:14.123456',INTERVAL 1 MICROSECOND);-- 表示:2017-05-15 10:37:14.123455

-- 经特殊日期测试,DATE_SUB(date,INTERVAL expr type)可放心使用
SELECT DATE_SUB(CURDATE(),INTERVAL 1 DAY);-- 前一天:2017-05-11
SELECT DATE_SUB(CURDATE(),INTERVAL -1 DAY);-- 后一天:2017-05-13
SELECT DATE_SUB(CURDATE(),INTERVAL 1 MONTH);-- 一个月前日期:2017-04-12
SELECT DATE_SUB(CURDATE(),INTERVAL -1 MONTH);-- 一个月后日期:2017-06-12
SELECT DATE_SUB(CURDATE(),INTERVAL 1 YEAR);-- 一年前日期:2016-05-12
SELECT DATE_SUB(CURDATE(),INTERVAL -1 YEAR);-- 一年后日期:20178-06-12
-- MySQL date_sub() 日期时间函数 和 date_add() 用法一致,并且可以用INTERNAL -1 xxx的形式互换使用;
-- 另外,MySQL 中还有两个函数 subdate(), subtime(),建议,用 date_sub() 来替代。

-- MySQL 另类日期函数:period_add(P,N), period_diff(P1,P2)
-- 函数参数“P” 的格式为“YYYYMM” 或者 “YYMM”,第二个参数“N” 表示增加或减去 N month(月)。
-- MySQL period_add(P,N):日期加/减去N月。
SELECT PERIOD_ADD(201705,2), PERIOD_ADD(201705,-2);-- 201707 20170503
-- period_diff(P1,P2):日期 P1-P2,返回 N 个月。
SELECT PERIOD_DIFF(201706, 201703);--
-- datediff(date1,date2):两个日期相减 date1 - date2,返回天数
SELECT DATEDIFF('2017-06-05','2017-05-29');-- 7
-- TIMEDIFF(time1,time2):两个日期相减 time1 - time2,返回 TIME 差值
SELECT TIMEDIFF('2017-06-05 19:28:37', '2017-06-05 17:00:00');-- 02:28:37


-- MySQL日期转换函数
SELECT TIME_TO_SEC('01:00:05'); -- 3605
SELECT SEC_TO_TIME(3605);-- 01:00:05

-- MySQL (日期、天数)转换函数:to_days(date), from_days(days)
SELECT TO_DAYS('0000-00-00'); -- NULL
SELECT TO_DAYS('2017-06-05'); -- 736850
SELECT FROM_DAYS(0); -- '0000-00-00'
SELECT FROM_DAYS(736850); -- '2017-06-05'

-- MySQL Str to Date (字符串转换为日期)函数:str_to_date(str, format)

SELECT STR_TO_DATE('06.05.2017 19:40:30', '%m.%d.%Y %H:%i:%s');-- 2017-06-05 19:40:30
SELECT STR_TO_DATE('06/05/2017', '%m/%d/%Y'); -- 2017-06-05
SELECT STR_TO_DATE('2017/12/3','%Y/%m/%d') -- 2017-12-03
SELECT STR_TO_DATE('20:09:30', '%h:%i:%s') -- NULL(超过12时的小时用小写h,得到的结果为NULL)

-- 日期时间格式化
SELECT DATE_FORMAT('2017-05-12 17:03:51', '%Y年%m月%d日 %H时%i分%s秒');-- 2017年05月12日 17时03分51秒(具体需要什么格式的数据根据实际情况来;小写h为12小时制;)
SELECT TIME_FORMAT('2017-05-12 17:03:51', '%Y年%m月%d日 %H时%i分%s秒');-- 0000年00月00日 17时03分51秒(time_format()只能用于时间的格式化)
-- STR_TO_DATE()和DATE_FORMATE()为互逆操作

-- MySQL 获得国家地区时间格式函数:get_format()
-- MySQL get_format() 语法:get_format(date|time|datetime, 'eur'|'usa'|'jis'|'iso'|'internal'
-- MySQL get_format() 用法的全部示例:
SELECT GET_FORMAT(DATE,'usa'); -- '%m.%d.%Y'
SELECT GET_FORMAT(DATE,'jis'); -- '%Y-%m-%d'
SELECT GET_FORMAT(DATE,'iso'); -- '%Y-%m-%d'
SELECT GET_FORMAT(DATE,'eur'); -- '%d.%m.%Y'
SELECT GET_FORMAT(DATE,'internal'); -- '%Y%m%d'
SELECT GET_FORMAT(DATETIME,'usa'); -- '%Y-%m-%d %H.%i.%s'
SELECT GET_FORMAT(DATETIME,'jis'); -- '%Y-%m-%d %H:%i:%s'
SELECT GET_FORMAT(DATETIME,'iso'); -- '%Y-%m-%d %H:%i:%s'
SELECT GET_FORMAT(DATETIME,'eur'); -- '%Y-%m-%d %H.%i.%s'
SELECT GET_FORMAT(DATETIME,'internal'); -- '%Y%m%d%H%i%s'
SELECT GET_FORMAT(TIME,'usa'); -- '%h:%i:%s %p'
SELECT GET_FORMAT(TIME,'jis'); -- '%H:%i:%s'
SELECT GET_FORMAT(TIME,'iso'); -- '%H:%i:%s'
SELECT GET_FORMAT(TIME,'eur'); -- '%H.%i.%s'
SELECT GET_FORMAT(TIME,'internal'); -- '%H%i%s'


-- MySQL 拼凑日期、时间函数:makdedate(year,dayofyear), maketime(hour,minute,second)
SELECT MAKEDATE(2017,31); -- '2017-01-31'
SELECT MAKEDATE(2017,32); -- '2017-02-01'
SELECT MAKETIME(19,52,35); -- '19:52:35'

-- MySQL 时区(timezone)转换函数:convert_tz(dt,from_tz,to_tz)
SELECT CONVERT_TZ('2017-06-05 19:54:12', '+08:00', '+00:00'); -- 2017-06-05 11:54:12


-- MySQL (Unix 时间戳、日期)转换函数
-- unix_timestamp(), unix_timestamp(date), from_unixtime(unix_timestamp), from_unixtime(unix_timestamp,format)
-- 将具体时间时间转为timestamp
SELECT UNIX_TIMESTAMP();-- 当前时间的时间戳:1494815779
SELECT UNIX_TIMESTAMP('2017-05-15');-- 指定日期的时间戳:1494777600
SELECT UNIX_TIMESTAMP('2017-05-15 10:37:14');-- 指定日期时间的时间戳:1494815834

-- 将时间戳转为具体时间
SELECT FROM_UNIXTIME(1494815834);-- 2017-05-15 10:37:14
SELECT FROM_UNIXTIME(1494815834, '%Y年%m月%d日 %h时%分:%s秒');-- 获取时间戳对应的格式化日期时间

-- MySQL 时间戳(timestamp)转换、增、减函数
SELECT TIMESTAMP('2017-05-15');-- 2017-05-15 00:00:00
SELECT TIMESTAMP('2017-05-15 08:12:25', '01:01:01');-- 2017-05-15 09:13:26
SELECT DATE_ADD('2017-05-15 08:12:25', INTERVAL 1 DAY);-- 2017-05-16 08:12:25
SELECT TIMESTAMPADD(DAY, 1, '2017-05-15 08:12:25');-- 2017-05-16 08:12:25; MySQL timestampadd() 函数类似于 date_add()。

SELECT TIMESTAMPDIFF(YEAR, '2017-06-01', '2016-05-15');-- -1
SELECT TIMESTAMPDIFF(MONTH, '2017-06-01', '2016-06-15');-- -11
SELECT TIMESTAMPDIFF(DAY, '2017-06-01', '2016-06-15');-- -351
SELECT TIMESTAMPDIFF(HOUR, '2017-06-01 08:12:25', '2016-06-15 00:00:00');-- -8432
SELECT TIMESTAMPDIFF(MINUTE, '2017-06-01 08:12:25', '2016-06-15 00:00:00');-- -505932
SELECT TIMESTAMPDIFF(SECOND, '2017-06-01 08:12:25', '2016-06-15 00:00:00');-- -30355945

1.7 自动赋值时间戳

官方文档:https://dev.mysql.com/doc/refman/8.0/en/timestamp-initialization.html

MySQL有时间函数,也可以在插入和操作数据的时候自动帮我们更新时间。下面是一个示例语句,在TIMESTAMP和DATETIME类型中都可以这么使用。

1
2
3
4
CREATE TABLE t1 (
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
dt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

ON UPDATE语句的含义为当行被更新的时候,就自动更新为当前时间(即更新时间)

举个具体的例子:用户表中,我们的一条记录可以有两个时间字段,一个是更新时间,即用户信息被用户修改后的时间(这个时间可以用来限制用户多久才能修改一次个人信息等操作),另外一个是插入时间,即用户注册的时间。

此时可以让MySQL来自动帮我们维护插入时间和更新时间。

1
2
3
4
5
6
CREATE TABLE your_table (
id INT PRIMARY KEY,
data VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

2.字符串函数

函数作用
charset(str)返回字符串的字符集
concat(str1,str2[,…])拼接多个字符串
instr(str,substr)返回substr在str中出现的位置,不存在则返回0
ucase(string)字符串转大写
lcase(string)字符串转小写
left(string,length)/right(string,length)从string的左边/右边起取length个字符
length(string)字符串长度
replace(str,search_str,replace_str)将str中的replace_str部分替换为search_str
strcmp(str1,str2)逐字符比较两个字符串的大小
substring(str,position [,length])从str的position开始取length个字符
ltrim(strin)/rtrim(str)/trim(str)去除字符串中的前空格或者后空格

简单测试一下这些函数的使用吧

2.1 查看字符串字符集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
MariaDB [stu_test]> select charset("你好");
+-------------------+
| charset("你好") |
+-------------------+
| utf8mb3 |
+-------------------+
1 row in set (0.000 sec)

MariaDB [stu_test]> select charset("125412446");
+----------------------+
| charset("125412446") |
+----------------------+
| utf8mb3 |
+----------------------+
1 row in set (0.000 sec)

MariaDB [stu_test]> select charset(name) from student;
+---------------+
| charset(name) |
+---------------+
| utf8mb4 |
| utf8mb4 |
| utf8mb4 |
| utf8mb4 |
| utf8mb4 |
+---------------+
5 rows in set (0.000 sec)

2.2 字符串拼接

1
2
3
4
5
6
7
MariaDB [stu_test]> select concat('你好',',','今天天气不错');
+---------------------------------------------+
| concat('你好',',','今天天气不错') |
+---------------------------------------------+
| 你好,今天天气不错 |
+---------------------------------------------+
1 row in set (0.000 sec)

2.3 子字符串查询

使用instr查询,在第一个参数中查询第二个参数的字符串。找到了子串后,返回起始位置的偏移量(并非下标),没有找到返回0。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
MariaDB [stu_test]> select instr('abcdef','bc');
+----------------------+
| instr('abcdef','bc') |
+----------------------+
| 2 |
+----------------------+
1 row in set (0.000 sec)

MariaDB [stu_test]> select instr('abcdef','asdfa');
+-------------------------+
| instr('abcdef','asdfa') |
+-------------------------+
| 0 |
+-------------------------+
1 row in set (0.000 sec)

2.4 字符串比较

和C语言中用的是同一个函数名strcmp;

  • 第一个字符串更大返回1
  • 第二个字符串更大返回-1
  • 两个字符串相同返回0(忽略大小写);

注意它的比较是根据字符的ASCII码来逐字符比较的,比如小写字母的ASCII码就更大,所以AB和ad比较的结果是负一。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
MariaDB [stu_test]> select strcmp('AB','AB');
+-------------------+
| strcmp('AB','AB') |
+-------------------+
| 0 |
+-------------------+
1 row in set (0.000 sec)

MariaDB [stu_test]> select strcmp('AB','aB');
+-------------------+
| strcmp('AB','aB') |
+-------------------+
| 0 |
+-------------------+
1 row in set (0.000 sec)

MariaDB [stu_test]> select strcmp('AB','ad');
+-------------------+
| strcmp('AB','ad') |
+-------------------+
| -1 |
+-------------------+
1 row in set (0.000 sec)

MariaDB [stu_test]> select strcmp('AB','ABC');
+--------------------+
| strcmp('AB','ABC') |
+--------------------+
| -1 |
+--------------------+
1 row in set (0.000 sec)

MariaDB [stu_test]> select strcmp('ABcd','ABC');
+----------------------+
| strcmp('ABcd','ABC') |
+----------------------+
| 1 |
+----------------------+
1 row in set (0.000 sec)

中文比较应该也是类似的逻辑,只不过中文编码这方面我不太懂,就不深入探究了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
MariaDB [stu_test]> select strcmp('你好','你好吗');
+------------------------------+
| strcmp('你好','你好吗') |
+------------------------------+
| -1 |
+------------------------------+
1 row in set (0.000 sec)

MariaDB [stu_test]> select strcmp('你好','你');
+------------------------+
| strcmp('你好','你') |
+------------------------+
| 1 |
+------------------------+
1 row in set (0.000 sec)

MariaDB [stu_test]> select strcmp('你好','你好');
+---------------------------+
| strcmp('你好','你好') |
+---------------------------+
| 0 |
+---------------------------+
1 row in set (0.000 sec)

MariaDB [stu_test]> select strcmp('你好','在吗');
+---------------------------+
| strcmp('你好','在吗') |
+---------------------------+
| -1 |
+---------------------------+
1 row in set (0.000 sec)

2.5 大小写转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
MariaDB [stu_test]> select ucase('adfasbasdf324r');
+-------------------------+
| ucase('adfasbasdf324r') |
+-------------------------+
| ADFASBASDF324R |
+-------------------------+
1 row in set (0.000 sec)

MariaDB [stu_test]> select lcase('ADSB3QRdsadsfweq2');
+----------------------------+
| lcase('ADSB3QRdsadsfweq2') |
+----------------------------+
| adsb3qrdsadsfweq2 |
+----------------------------+
1 row in set (0.000 sec)

2.6 截取字符串

left和right用于从字符串的左边或右边开始截取给定长度的串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
MariaDB [stu_test]> select left('123456',2);
+------------------+
| left('123456',2) |
+------------------+
| 12 |
+------------------+
1 row in set (0.000 sec)

MariaDB [stu_test]> select right('123456',2);
+-------------------+
| right('123456',2) |
+-------------------+
| 56 |
+-------------------+
1 row in set (0.000 sec)

对于中文而言也是截取两个汉字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
MariaDB [stu_test]> select right('这是一个测试',2);
+-------------------------------+
| right('这是一个测试',2) |
+-------------------------------+
| 测试 |
+-------------------------------+
1 row in set (0.000 sec)

MariaDB [stu_test]> select left('这是一个测试',2);
+------------------------------+
| left('这是一个测试',2) |
+------------------------------+
| 这是 |
+------------------------------+
1 row in set (0.000 sec)

然后还有substring函数,可以从给定位置截取字符串

1
2
3
4
5
6
7
MariaDB [stu_test]> select substring('123456',2,2);
+-------------------------+
| substring('123456',2,2) |
+-------------------------+
| 23 |
+-------------------------+
1 row in set (0.000 sec)

2.7 去除空格

ltrim和rtrim用于去除字符串左侧或者右侧的空格

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
MariaDB [stu_test]> select ltrim(' 测试');
+------------------+
| ltrim(' 测试') |
+------------------+
| 测试 |
+------------------+
1 row in set (0.000 sec)

MariaDB [stu_test]> select rtrim('右边空格测试 ');
+-------------------------------------------+
| rtrim('右边空格测试 ') |
+-------------------------------------------+
| 右边空格测试 |
+-------------------------------------------+
1 row in set (0.000 sec)

trim是同时去除字符串左侧和右侧的空格,不会对字符串内部的空格做操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
MariaDB [stu_test]> select trim(' 空 格 去除测试 ');
+--------------------------------+
| trim( '空 格 去除测试 ') |
+--------------------------------+
| 空 格 去除测试 |
+--------------------------------+
1 row in set (0.000 sec)

MariaDB [stu_test]> select trim('空 格 去除测试');
+------------------------------+
| trim('空 格 去除测试') |
+------------------------------+
| 空 格 去除测试 |
+------------------------------+
1 row in set (0.000 sec)

2.8 字符串长度

注意,当前为了支持中文,我们使用了utf8作为MySQL的字符集,在utf8中中文是3字节存储的

1
2
3
4
5
6
7
8
9
10
11
MariaDB [stu_test]> select *,length(name) from stu;
+------+--------+--------------+
| id | name | length(name) |
+------+--------+--------------+
| 1 | jack | 4 |
| 2 | tom | 3 |
| 3 | kity | 4 |
| 4 | nono | 4 |
| 5 | 小明 | 6 |
+------+--------+--------------+
5 rows in set (0.000 sec)

3.数学函数

函数作用
abs(num)绝对值
bin(decimal_num)十进制转二进制
hex(decimal_num)十进制转十六进制
conv(num,from_base,to_base)进制转换
ceiling(num)向上取整
floor(num)向下取整
rand()返回随机浮点数,范围[0.0, 1.0)
mod(num,denominator)取模,求余
format(num,dnum)保留num的dnum位小数

3.1 绝对值

1
2
3
4
5
6
7
MariaDB [stu_test]> select abs(-1241.12431);
+------------------+
| abs(-1241.12431) |
+------------------+
| 1241.12431 |
+------------------+
1 row in set (0.000 sec)

3.2 进制转换

十进制转二进制和十六进制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
MariaDB [stu_test]> select bin(100);
+----------+
| bin(100) |
+----------+
| 1100100 |
+----------+
1 row in set (0.000 sec)

MariaDB [stu_test]> select hex(100);
+----------+
| hex(100) |
+----------+
| 64 |
+----------+
1 row in set (0.000 sec)

在任意进制中转换,源进制和目标进制都是通过数字传入,比如2/8/10/16

1
conv(目标数字,源进制,目标进制);

测试如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
MariaDB [stu_test]> select conv(100,2,16);
+----------------+
| conv(100,2,16) |
+----------------+
| 4 |
+----------------+
1 row in set (0.000 sec)

MariaDB [stu_test]> select conv(100,16,10);
+-----------------+
| conv(100,16,10) |
+-----------------+
| 256 |
+-----------------+
1 row in set (0.000 sec)

MariaDB [stu_test]> select conv(100,2,10);
+----------------+
| conv(100,2,10) |
+----------------+
| 4 |
+----------------+
1 row in set (0.000 sec)

3.3 向下和向上取整

向下取整和向上取整是基于小数的

  • 向下取整:不管小数有几位,都去除小数,整数部分不变;
  • 向上取整:不管小数有几位,都去除小数,并把整数部分加一;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
MariaDB [stu_test]> select ceiling(99);
+-------------+
| ceiling(99) |
+-------------+
| 99 |
+-------------+
1 row in set (0.000 sec)

MariaDB [stu_test]> select floor(99.1);
+-------------+
| floor(99.1) |
+-------------+
| 99 |
+-------------+
1 row in set (0.000 sec)

MariaDB [stu_test]> select ceiling(99.2);
+---------------+
| ceiling(99.2) |
+---------------+
| 100 |
+---------------+
1 row in set (0.000 sec)

3.4 模运算

1
mod(a,b); -- 等价于 a/b 的余数

效果如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
MariaDB [stu_test]> SELECT MOD(17, 5);
+------------+
| MOD(17, 5) |
+------------+
| 2 |
+------------+
1 row in set (0.000 sec)

MariaDB [stu_test]> SELECT MOD(15, 5);
+------------+
| MOD(15, 5) |
+------------+
| 0 |
+------------+
1 row in set (0.000 sec)

MariaDB [stu_test]> SELECT MOD(13, 5);
+------------+
| MOD(13, 5) |
+------------+
| 3 |
+------------+
1 row in set (0.000 sec)

3.5 小数格式化

使用format函数,第二个参数指定保留几位小数。

1
2
3
4
5
6
7
MariaDB [stu_test]> select format(3.1415,2);
+------------------+
| format(3.1415,2) |
+------------------+
| 3.14 |
+------------------+
1 row in set (0.000 sec)

3.6 获取随机数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
MariaDB [stu_test]> select rand();
+--------------------+
| rand() |
+--------------------+
| 0.5338426274562652 |
+--------------------+
1 row in set (0.000 sec)

MariaDB [stu_test]> select rand();
+--------------------+
| rand() |
+--------------------+
| 0.7618099523352552 |
+--------------------+
1 row in set (0.000 sec)

4.其他函数

函数作用
user()查询当前用户
database()查询当前所在数据库
password(str)对密码进行加密
md5(str)计算字符串的md5
ifnull(val1,val2)如果val1为null,返回val2,否则返回val1

这里只对ifnull函数做个测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
MariaDB [stu_test]> select ifnull(null,'124');
+--------------------+
| ifnull(null,'124') |
+--------------------+
| 124 |
+--------------------+
1 row in set (0.000 sec)

MariaDB [stu_test]> select ifnull('aba','124');
+---------------------+
| ifnull('aba','124') |
+---------------------+
| aba |
+---------------------+
1 row in set (0.000 sec)

MariaDB [stu_test]> select ifnull('','124');
+------------------+
| ifnull('','124') |
+------------------+
| |
+------------------+
1 row in set (0.000 sec)

The end

关于MySQL内置函数的章节就这些了,如果后续遇到本文没有记录的函数,会更新本文!