09 内置函数上

内置函数上

1. 日期函数

1. 常用日期函数一览

日期函数主要干三件事:取时间、算时间、按时间筛选。

顺序使用场景函数名称(含参数与含义)说明
1获取当前时间NOW() / CURRENT_TIMESTAMP()当前日期 + 时间
CURDATE() / CURRENT_DATE()当前日期
CURTIME() / CURRENT_TIME()当前时间
2取日期 / 时间部分DATE(datetime)(取日期部分)常用于按天统计
TIME(datetime)(取时间部分)仅保留时分秒
3从时间中取字段YEAR(datetime) / MONTH(datetime) / DAY(datetime)提取年/月/日
HOUR(datetime) / MINUTE(datetime) / SECOND(datetime)提取时/分/秒
4时间加减计算DATE_ADD(date, INTERVAL n unit)(date + n 个时间单位)时间往后推
DATE_SUB(date, INTERVAL n unit)(date − n 个时间单位)时间往前推
5时间差计算(天)DATEDIFF(date1, date2)(date1 − date2,单位:天)只算日期,不管时分秒
6时间差计算(精确)TIMESTAMPDIFF(unit, start, end)(end − start,可指定单位)可算秒/分/小时/天/年
7时间格式化(展示)DATE_FORMAT(datetime, format)(按 format 输出字符串)仅影响显示
8字符串转时间STR_TO_DATE(str, format)(按 format 解析字符串为时间)用于入库/比较
9时间条件筛选(查询)WHERE 时间字段 < / > / <= / >= DATE_ADD(...) / DATE_SUB(...)时间范围筛选

2. 获取当前时间的函数

1. NOW()(常用)

1
2
3
4
5
6
mysql> select now();
+---------------------+
| now() |
+---------------------+
| 2025-12-14 22:35:20 |
+---------------------+

用途:记录创建时间、更新时间。

1
2
3
4
5
6
7
CREATE TABLE student (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(20) NOT NULL,
age INT,
create_time DATETIME DEFAULT NOW(), # 插入时默认用当前时间(等价于NOW())
update_time DATETIME DEFAULT NOW() ON UPDATE CURRENT_TIMESTAMP # 插入默认NOW(),更新自动刷新
);

2. CURRENT_TIMESTAMP(和 NOW 类似)

1
2
3
4
5
6
mysql> select current_timestamp();
+---------------------+
| current_timestamp() |
+---------------------+
| 2025-12-14 22:46:59 |
+---------------------+

3. CURDATE()CURRENT_DATE()/CURTIME()CURRENT_TIME()

1
2
3
4
SELECT CURDATE(); 		# 当前日期
SELECT CURRENT_DATE() # 当前日期
SELECT CURTIME(); # 当前时间
SELECT CURRENT_TIME() # 当前时间
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
mysql> select current_date();
+----------------+
| current_date() |
+----------------+
| 2025-12-14 |
+----------------+

mysql> select current_time();
+----------------+
| current_time() |
+----------------+
| 22:34:25 |
+----------------+

mysql> select curdate();
+------------+
| curdate() |
+------------+
| 2025-12-14 |
+------------+

mysql> select curtime();
+-----------+
| curtime() |
+-----------+
| 22:42:30 |
+-----------+

3. 从时间中“取字段”(常用)

参数统一为:日期/时间字段(DATETIME/DATE/TIME)、标准格式字符串(符合 YYYY-MM-DD/HH: MM: SS 的字符串)、日期函数结果(返回日期/时间的函数,相当于函数嵌套了)。

1. YEAR/MONTH/DAY(年/月/日)

1
2
3
4
5
6
# 拆分订单创建时间的年、月、日
SELECT
YEAR(created_at) AS 订单年份, # 提取年份
MONTH(created_at) AS 订单月份, # 提取月份
DAY(created_at) AS 订单日期 # 提取日期
FROM orders;

2. HOUR/MINUTE/SECOND(时/分/秒)

1
2
3
4
5
6
# 拆分订单创建时间的时、分、秒
SELECT
HOUR(created_at) AS 订单小时, # 提取小时(24小时制)
MINUTE(created_at) AS 订单分钟, # 提取分
SECOND(created_at) AS 订单秒 # 提取秒
FROM orders;

3. DATE() / TIME()(高频)

1
2
3
4
5
6
7
8
SELECT DATE(created_at), TIME(created_at) FROM orders;

mysql> select date(now());
+-------------+
| date(now()) |
+-------------+
| 2025-12-14 |
+-------------+

4. 时间计算函数(高频)

1. DATE_ADD() / DATE_SUB()

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
# 给当前时间(now())加7天 → 结果是7天后的同一时间
mysql> select date_add(now(), interval 7 day);
+---------------------------------+
| date_add(now(), interval 7 day) |
+---------------------------------+
| 2025-12-22 13:18:36 | # 当前时间+7天的结果
+---------------------------------+

# date_add传负数:给当前时间减10天 → 结果是10天前的同一时间
mysql> select date_add(now(), interval -10 day);
+-----------------------------------+
| date_add(now(), interval -10 day) |
+-----------------------------------+
| 2025-12-05 13:19:21 | # 当前时间-10天的结果
+-----------------------------------+

# 给当前时间减5天 → 结果是5天前的同一时间
mysql> select date_sub(now(),interval 5 day);
+--------------------------------+
| date_sub(now(),interval 5 day) |
+--------------------------------+
| 2025-12-10 13:20:12 | # 当前时间-5天的结果
+--------------------------------+

# date_sub传负数:给当前时间加1年 → 结果是1年后的同一时间
mysql> select date_sub(now(),interval -1 year);
+----------------------------------+
| date_sub(now(),interval -1 year) |
+----------------------------------+
| 2026-12-15 13:20:50 | # 当前时间+1年的结果
+----------------------------------+

常见单位:SECOND (秒)、MINUTE (分钟)、HOUR (小时)、DAY (天)、WEEK (周)、MONTH (月)、YEAR (年)。

2. DATEDIFF()(算天数)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 说明:只算天,不管时分秒。
# datediff(日期1, 日期2):计算日期1 - 日期2的天数差(仅算日期,忽略时分秒)
mysql> select datediff('2000.01.01',now());
+------------------------------+
| datediff('2000.01.01',now()) |
+------------------------------+
| -9480 | # 2000-01-01 比 当前时间 早9480天,结果为负
+------------------------------+

# 计算当前时间 - 1999-09-09 的天数差(仅算日期,忽略时分秒)
mysql> select datediff(now(), "1999-09-09");
+-------------------------------+
| datediff(now(), "1999-09-09") |
+-------------------------------+
| 9594 | # 当前时间 比 1999-09-099594天,结果为正
+-------------------------------+

3. TIMESTAMPDIFF()(更精确)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# timestampdiff(单位, 起始时间, 结束时间):计算结束时间-起始时间的时间差,按指定单位返回
mysql> select timestampdiff(hour,'1999-09-09',now());
+----------------------------------------+
| timestampdiff(hour,'1999-09-09',now()) |
+----------------------------------------+
| 230269 | # 1999-09-09到当前时间的小时差
+----------------------------------------+

mysql> select timestampdiff(day,'1999-09-09',now());
+---------------------------------------+
| timestampdiff(day,'1999-09-09',now()) |
+---------------------------------------+
| 9594 | # 1999-09-09到当前时间的天数差
+---------------------------------------+

mysql> select timestampdiff(year,'1999-09-09',now());
+----------------------------------------+
| timestampdiff(year,'1999-09-09',now()) |
+----------------------------------------+
| 26 | # 1999-09-09到当前时间的年数差
+----------------------------------------+

5. 格式化与解析时间

1. DATE_FORMAT()(展示用)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# date_format(时间, 格式化方式):自定义格式输出日期时间
mysql> select date_format(now(),"%Y-%m-%d");
+-------------------------------+
| date_format(now(),"%Y-%m-%d") |
+-------------------------------+
| 2025-12-15 |
+-------------------------------+

mysql> select date_format(now(),"%Y-%M-%D");
+-------------------------------+
| date_format(now(),"%Y-%M-%D") |
+-------------------------------+
| 2025-December-15th |
+-------------------------------+

mysql> select date_format(now(),"%y-%m-%d %h-%i-%s");
+----------------------------------------+
| date_format(now(),"%y-%m-%d %h-%i-%s") |
+----------------------------------------+
| 25-12-15 01-40-29 |
+----------------------------------------+

注意:小写多为精简数字格式(如 %y = 2 位年、%m = 数字月、%h = 12 小时制),大写多为完整/英文格式(如 %Y = 4 位年、%M = 英文月、%H = 24 小时制),仅秒无区别、分钟仅小写 %i。

2. STR_TO_DATE()(字符串转时间)

注意:字符串用 - 分隔年月日,格式符也必须写 %Y-%m-%d(用 -),如果字符串用 ./ 分隔,格式符需对应写成 %Y.%m.%d%Y/%m/%d,否则解析失败返回 NULL。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
mysql> select str_to_date('2025-01-01 10:00:00','%Y-%m-%d %H:%i:%s');
+--------------------------------------------------------+
| str_to_date('2025-01-01 10:00:00','%Y-%m-%d %H:%i:%s') |
+--------------------------------------------------------+
| 2025-01-01 10:00:00 |
+--------------------------------------------------------+

mysql> select str_to_date('2025/01/01 10:00:00','%Y-%m-%d %H:%i:%s');
+--------------------------------------------------------+
| str_to_date('2025/01/01 10:00:00','%Y-%m-%d %H:%i:%s') |
+--------------------------------------------------------+
| NULL |
+--------------------------------------------------------+

mysql> select str_to_date('2025/01/01 10:00:00','%Y/%m/%d %H:%i:%s');
+--------------------------------------------------------+
| str_to_date('2025/01/01 10:00:00','%Y/%m/%d %H:%i:%s') |
+--------------------------------------------------------+
| 2025-01-01 10:00:00 |
+--------------------------------------------------------+

6. 时间筛选

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
# 创建t4表:含自增ID、评论内容、创建时间(默认当前时间)、更新时间(更新时自动刷新)
mysql> create table t4(
id int auto_increment primary key,
content varchar(500) not null,
create_time datetime default now(),
update_time datetime default now() on update now());

# 插入2条测试数据:手动指定第一条的创建时间,第二条用当前时间
mysql> insert into t4(content,create_time) values
('我是小米里的大麦','2025-01-01 10:00:00'),
("喜欢就点个关注吧",now());

# 查看表中所有数据
mysql> select * from t4;
+----+--------------------------+---------------------+---------------------+
| id | content | create_time | update_time |
+----+--------------------------+---------------------+---------------------+
| 1 | 我是小米里的大麦 | 2025-01-01 10:00:00 | 2025-12-15 17:08:13 |
| 2 | 喜欢就点个关注吧 | 2025-12-15 17:08:13 | 2025-12-15 17:08:13 |
+----+--------------------------+---------------------+---------------------+

# 筛选创建时间≤2025-12-31的记录(两条都满足)
mysql> select id,content,create_time from t4 where create_time<='2025-12-31';
+----+--------------------------+---------------------+
| id | content | create_time |
+----+--------------------------+---------------------+
| 1 | 我是小米里的大麦 | 2025-01-01 10:00:00 |
| 2 | 喜欢就点个关注吧 | 2025-12-15 17:08:13 |
+----+--------------------------+---------------------+

# 筛选创建时间≤2025-10-31的记录(仅第一条满足)
mysql> select id,content,create_time from t4 where create_time<='2025-10-31';
+----+--------------------------+---------------------+
| id | content | create_time |
+----+--------------------------+---------------------+
| 1 | 我是小米里的大麦 | 2025-01-01 10:00:00 |
+----+--------------------------+---------------------+

# 新增2条数据:仅传内容,创建/更新时间默认当前时间
mysql> insert into t4(content) values
("hhhh哈哈哈哈"),("今天是个悲伤的日子");

# 找出10分钟前创建的数据
mysql> select id,content,create_time,update_time from t4 where create_time<date_sub(now(),interval 10 minute);
+----+--------------------------+---------------------+---------------------+
| id | content | create_time | update_time |
+----+--------------------------+---------------------+---------------------+
| 1 | 我是小米里的大麦 | 2025-01-01 10:00:00 | 2025-12-15 17:08:13 |
| 2 | 喜欢就点个关注吧 | 2025-12-15 17:08:13 | 2025-12-15 17:08:13 |
+----+--------------------------+---------------------+---------------------+

# 找出10分钟更新的数据
mysql> select id,content,create_time,update_time from t4 where update_time<date_sub(now(),interval 10 minute);
+----+--------------------------+---------------------+---------------------+
| id | content | create_time | update_time |
+----+--------------------------+---------------------+---------------------+
| 1 | 我是小米里的大麦 | 2025-01-01 10:00:00 | 2025-12-15 17:08:13 |
| 2 | 喜欢就点个关注吧 | 2025-12-15 17:08:13 | 2025-12-15 17:08:13 |
+----+--------------------------+---------------------+---------------------+

# 找出最近10分钟更新的数据
mysql> select id,content,create_time,update_time from t4 where update_time>date_sub(now(),interval 10 minute);
+----+-----------------------------+---------------------+---------------------+
| id | content | create_time | update_time |
+----+-----------------------------+---------------------+---------------------+
| 3 | hhhh哈哈哈哈 | 2025-12-15 17:15:35 | 2025-12-15 17:15:35 |
| 4 | 今天是个悲伤的日子 | 2025-12-15 17:15:35 | 2025-12-15 17:15:35 |
+----+-----------------------------+---------------------+---------------------+

# 找出创建时间晚于2025310日的数据
mysql> select id,content,create_time from t4 where create_time > date_add('2024-10-10',interval 5 month);
+----+-----------------------------+---------------------+
| id | content | create_time |
+----+-----------------------------+---------------------+
| 2 | 喜欢就点个关注吧 | 2025-12-15 17:08:13 |
| 3 | hhhh哈哈哈哈 | 2025-12-15 17:15:35 |
| 4 | 今天是个悲伤的日子 | 2025-12-15 17:15:35 |
+----+-----------------------------+---------------------+

# 找出创建时早于2025310日的数据
mysql> select id,content,create_time from t4 where create_time < date_add('2024-10-10',interval 5 month);
+----+--------------------------+---------------------+
| id | content | create_time |
+----+--------------------------+---------------------+
| 1 | 我是小米里的大麦 | 2025-01-01 10:00:00 |
+----+--------------------------+---------------------+

2. 字符串函数

MySQL 常用字符串函数包括长度、拼接、截取、替换和查找等,展示和处理可以用,WHERE 中应避免对索引列使用函数以免索引失效。

使用场景函数参数解释说明 / 返回结果
长度计算LENGTH(str)str:要计算的字符串返回 字节长度,中文通常 3 字节
CHAR_LENGTH(str)str:要计算的字符串返回 字符个数(推荐使用)
大小写转换UPPER(str) / UCASE(str)str:原字符串转成大写
LOWER(str) / LCASE(str)str:原字符串转成小写
字符串拼接CONCAT(str1, str2, ...)str1,str2...:按顺序拼接只要有一个 NULL,结果就是 NULL
CONCAT_WS(sep, str1, str2, ...)sep:分隔符;后面是要拼的字符串自动忽略 NULL,推荐
截取子串SUBSTRING(str, start, len)str:原字符串;start从第几个字符开始(从 1 开始)len:取几个字符返回截取后的字符串
左右截取LEFT(str, n)n:从左边取 n 个字符常用于取前缀
RIGHT(str, n)n:从右边取 n 个字符常用于取后缀
去空格LTRIM(str)去掉字符串 左边 的空格返回新字符串
RTRIM(str)去掉字符串 右边 的空格
TRIM(str)去掉字符串 两端 的空格常用
字符串替换REPLACE(str, old, new)old:被替换的子串;new:新子串全部匹配都会被替换
定点替换INSERT(str, pos, len, new_str)pos从第几个字符开始(从 1 开始)len:删掉几个字符;new_str:插入的新内容先删再插
查找位置INSTR(str, sub)sub:要找的子串返回位置(从 1 开始),找不到返回 0
LOCATE(sub, str)INSTR 一样,只是参数顺序相反
字符串比较STRCMP(str1, str2)比较 str1str2 的大小相等 0,大于 1,小于 -1
模糊匹配LIKE%:任意长度;_:一个字符常用于前缀/模糊查询
字符集查看CHARSET(str)查看字符串当前使用的字符集调试用,一般较少用

1. 字符串长度相关

1. LENGTH() —— 字节长度

1
2
3
4
5
LENGTH(str)

mysql> select length(6); # 1
mysql> select length('abcd'); # 4
mysql> select length('你好'); # 6

注意:算的是 字节,中文通常 3 字节。

2. CHAR_LENGTH() —— 字符长度(推荐)

1
2
3
4
5
CHAR_LENGTH(str)

mysql> select length(6); # 1
mysql> select length('abcd'); # 4
mysql> select length('你好'); # 2

2. 大小写转换(UCASE()UPPER() / LCASE()LOWER()

1
2
3
4
5
6
7
UPPER(str)/UCASE(str)
LOWER(str)/LCASE(str)

select ucase("abc"); # ABC
select upper("abc"); # ABC
select lcase("ABC"); # abc
select lower("ABC"); # abc

3. 字符串拼接(常用)

1. CONCAT()

1
2
3
4
CONCAT(str1, str2, ...)

select concat('hello','mysql'); # hellomysql
select concat(NULL,"dashdhsadh","dasjdkhsa"); # NULL

注意:只要 有一个是 NULL → 结果就是 NULL。

2. CONCAT_WS()(更安全)

1
2
3
4
CONCAT_WS(分隔符, str1, str2, ...)

select concat_ws(' ',"hellow","world"); # hellow world
select concat_ws('-','2025',NULL,'11'); # 2025-11(自动忽略 NULL)

4. 子串相关

1. SUBSTRING()(常用)

1
2
3
4
5
6
7
8
9
10
11
12
SUBSTRING(str, start, len)
select substring('abcdefg',2,5); # bcdef(和C++的substr基本是一样的)

mysql> select substring('abcdefg',10);
+-------------------------+
| substring('abcdefg',10) |
+-------------------------+
| |
+-------------------------+

mysql> select substring('abcdefg',0,10); # 输出同上,就是没有,空的!
# 所以我们发现:只要起始位置/截取长度超出字符串范围,结果都是空字符串,没有区别!

2. LEFT() / RIGHT()

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
LEFT(str, n)	# LEFT(字符串, 要截取的个数):从最左边开始,截取x个字符
RIGHT(str, n) # RIGHT(字符串, 要截取的个数):从最右边开始,截取x个字符
# 哪怕超长度,也返回完整字符串,绝不空!只有截取个数=0时,才会空,这是和 SUBSTRING 最核心的区别(SUBSTRING 起始位超了就空)
mysql> select left("abcd",4);
+----------------+
| left("abcd",4) |
+----------------+
| abcd |
+----------------+

mysql> select left("abcd",6);
+----------------+
| left("abcd",6) |
+----------------+
| abcd |
+----------------+

mysql> select right("abcd",3);
+-----------------+
| right("abcd",3) |
+-----------------+
| bcd |
+-----------------+

mysql> select right("abcd",6);
+-----------------+
| right("abcd",6) |
+-----------------+
| abcd |
+-----------------+

5. 去空格(LTRIM() / RTRIM() / TRIM()

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
LTRIM(str)  # 去左空格
RTRIM(str) # 去右空格
TRIM(str) # 两边都去

# 1. LTRIM:只剪左边,右边空格保留
mysql> select ltrim(" abc 123 ");
+-------------------------+
| ltrim(" abc 123 ") |
+-------------------------+
| abc 123 | # 左边空没了,右边空还在
+-------------------------+

# 2. RTRIM:只剪右边,左边空格保留
mysql> select rtrim(" abc 123 ");
+--------------------------+
| rtrim(" abc 123 ") |
+--------------------------+
| abc 123 | # 右边空没了,左边空还在
+--------------------------+

# 3. TRIM:左右都剪,中间空格保留
mysql> select trim(" abc 123 ");
+------------------------+
| trim(" abc 123 ") |
+------------------------+
| abc 123 | # 左右空都没了,中间的“abc和123之间”的空还在
+------------------------+

6. 字符串替换

1. REPLACE()

1
2
3
4
5
6
7
8
9
REPLACE(str, old, new)
REPLACE(要操作的字符串, 要替换掉的内容, 替换成的新内容)

mysql> select replace("hello world","world","mysql");
+----------------------------------------+
| replace("hello world","world","mysql") |
+----------------------------------------+
| hello mysql |
+----------------------------------------+

2. INSERT()(少用但要认识)

1
2
3
4
5
6
7
8
9
INSERT(str, pos, len, new_str)
INSERT(原始字符串, 起始位置, 要删除的字符数, 要插入的新内容)

mysql> select insert("hellow world",2,5,"xxxxxxxxxxx");
+------------------------------------------+
| insert("hellow world",2,5,"xxxxxxxxxxx") |
+------------------------------------------+
| hxxxxxxxxxxx world |
+------------------------------------------+

7. 查找位置(INSTR() / LOCATE()

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
INSTR(str, sub)		# INSTR(被搜索的原始字符串, 要查找的子字符串)
LOCATE(sub, str) # LOCATE(要查找的子字符串, 被搜索的原始字符串)

mysql> select instr("hellow","he");
+----------------------+
| instr("hellow","he") |
+----------------------+
| 1 |
+----------------------+

mysql> select instr("hellow","hex");
+-----------------------+
| instr("hellow","hex") |
+-----------------------+
| 0 |
+-----------------------+

mysql> select locate("hex","hello");
+-----------------------+
| locate("hex","hello") |
+-----------------------+
| 0 |
+-----------------------+

mysql> select locate("he","hello");
+----------------------+
| locate("he","hello") |
+----------------------+
| 1 |
+----------------------+

8. 字符串比较

1. STRCMP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
STRCMP(str1, str2)

mysql> select strcmp("abc","abc");
+---------------------+
| strcmp("abc","abc") |
+---------------------+
| 0 |
+---------------------+

mysql> select strcmp("abc","ab");
+--------------------+
| strcmp("abc","ab") |
+--------------------+
| 1 |
+--------------------+

mysql> select strcmp("ab","abc");
+--------------------+
| strcmp("ab","abc") |
+--------------------+
| -1 |
+--------------------+

2. LIKE

准确来说 LIKE 不是字符串函数,他属于 SQL 匹配运算符(前面讲过),但这里提一下 = vs LIKE

1
2
WHERE name = 'tom';   # 精确
WHERE name LIKE 'tom'; # 等价但慢

9. 补充:CHARSET()(认识即可)

用于查看字符串使用的字符集

1
2
3
4
5
6
7
8
CHARSET(str)

mysql> select charset("abc");
+----------------+
| charset("abc") |
+----------------+
| utf8mb4 |
+----------------+