掌握 MySQL 内置函数,让数据查询与处理如虎添翼
在 MySQL 数据库开发中,内置函数是我们日常操作数据的重要工具。无论是日期计算、字符串处理,还是数值运算、类型转换,函数都能帮助我们高效地完成复杂任务。本文将系统讲解 MySQL 中常用的内置函数,并配合经典案例和易错点解析,助你快速上手并避坑。
📂 目录
- [1. 日期函数](#1. 日期函数)
- [1.1 获取当前日期/时间/时间戳](#1.1 获取当前日期/时间/时间戳)
- [1.2 日期加减运算](#1.2 日期加减运算)
- [1.3 日期差值计算](#1.3 日期差值计算)
- [1.4 提取日期部分](#1.4 提取日期部分)
- [1.5 经典案例:留言板时间筛选](#1.5 经典案例:留言板时间筛选)
- [1.6 易错点与补充](#1.6 易错点与补充)
- [2. 字符串函数](#2. 字符串函数)
- [2.1 字符集与字节长度](#2.1 字符集与字节长度)
- [2.2 拼接与格式化](#2.2 拼接与格式化)
- [2.3 替换与截取](#2.3 替换与截取)
- [2.4 大小写转换](#2.4 大小写转换)
- [2.5 经典案例:学生成绩单格式化](#2.5 经典案例:学生成绩单格式化)
- [2.6 易错点与补充](#2.6 易错点与补充)
- [3. 数学函数](#3. 数学函数)
- [3.1 绝对值与取整](#3.1 绝对值与取整)
- [3.2 进制转换](#3.2 进制转换)
- [3.3 随机数与格式化](#3.3 随机数与格式化)
- [3.4 易错点与补充](#3.4 易错点与补充)
- [4. 其他常用函数](#4. 其他常用函数)
- [4.1 用户与数据库信息](#4.1 用户与数据库信息)
- [4.2 加密与摘要](#4.2 加密与摘要)
- [4.3 空值处理](#4.3 空值处理)
- [4.4 条件判断(补充)](#4.4 条件判断(补充))
- [5. 实战 OJ 演练](#5. 实战 OJ 演练)
- [6. 总结与建议](#6. 总结与建议)
1. 日期函数
日期函数是日常开发中使用频率最高的函数类别,尤其适用于记录日志、统计报表、时效性查询等场景。
1.1 获取当前日期/时间/时间戳
| 函数 | 返回类型 | 说明 |
|---|---|---|
CURRENT_DATE() |
DATE | 当前日期(YYYY-MM-DD) |
CURRENT_TIME() |
TIME | 当前时间(HH:MM:SS) |
NOW() |
DATETIME | 当前日期+时间(YYYY-MM-DD HH:MM:SS) |
CURRENT_TIMESTAMP() |
DATETIME | 同 NOW(),但更强调时间戳语义 |
sql
-- 获取当前日期
SELECT CURRENT_DATE(); -- 2026-06-17
-- 获取当前时间
SELECT CURRENT_TIME(); -- 14:30:25
-- 获取完整时间戳
SELECT NOW(); -- 2026-06-17 14:30:25
SELECT CURRENT_TIMESTAMP(); -- 2026-06-17 14:30:25
1.2 日期加减运算
DATE_ADD(date, INTERVAL 数值 单位)DATE_SUB(date, INTERVAL 数值 单位)
单位支持:YEAR、MONTH、DAY、HOUR、MINUTE、SECOND、WEEK、QUARTER 等。
sql
-- 加 10 天
SELECT DATE_ADD('2026-06-17', INTERVAL 10 DAY); -- 2026-06-27
-- 减 2 个月
SELECT DATE_SUB('2026-06-17', INTERVAL 2 MONTH); -- 2026-04-17
-- 加 1 年零 3 天(可连续操作)
SELECT DATE_ADD(DATE_ADD('2026-06-17', INTERVAL 1 YEAR), INTERVAL 3 DAY);
-- 或使用更灵活的写法(后面会提到 ADDDATE/SUBDATE 别名)
💡 提示 :
DATE_ADD和DATE_SUB也可以写成ADDDATE/SUBDATE,用法相同。
1.3 日期差值计算
DATEDIFF(date1, date2) 返回 date1 - date2 的天数差(只比较日期部分,忽略时间)。
sql
SELECT DATEDIFF('2026-06-17', '2026-06-01'); -- 16
SELECT DATEDIFF('2026-06-01', '2026-06-17'); -- -16
注意 :如果传入 DATETIME 类型,时间部分不影响计算结果。
1.4 提取日期部分
DATE(datetime) 提取日期部分,YEAR()、MONTH()、DAY() 等也可单独提取。
sql
SELECT DATE(NOW()); -- 2026-06-17
SELECT YEAR(NOW()); -- 2026
SELECT MONTH(NOW()); -- 6
SELECT DAY(NOW()); -- 17
SELECT HOUR(NOW()); -- 14
SELECT MINUTE(NOW()); -- 30
1.5 经典案例:留言板时间筛选
场景 :有一个留言表 msg,包含 id、content、sendtime(DATETIME)。要求:
- 显示所有留言,但只显示日期(不显示时间)
- 查询最近 2 分钟内发布的帖子
建表及插入数据:
sql
CREATE TABLE msg (
id INT PRIMARY KEY AUTO_INCREMENT,
content VARCHAR(30) NOT NULL,
sendtime DATETIME
);
INSERT INTO msg(content, sendtime) VALUES
('hello1', NOW()),
('hello2', NOW());
(1)只显示日期:
sql
SELECT id, content, DATE(sendtime) AS send_date FROM msg;
输出示例:
+----+---------+------------+
| id | content | send_date |
+----+---------+------------+
| 1 | hello1 | 2026-06-17 |
| 2 | hello2 | 2026-06-17 |
+----+---------+------------+
(2)查询 2 分钟内发布的帖子:
sql
SELECT * FROM msg
WHERE sendtime > DATE_SUB(NOW(), INTERVAL 2 MINUTE);
-- 等价写法:WHERE DATE_ADD(sendtime, INTERVAL 2 MINUTE) > NOW()
⚠️ 易错 :很多人会写成
DATE_ADD(sendtime, INTERVAL 2 MINUTE) > NOW(),这个逻辑是"发送时间 + 2 分钟后 > 当前时间",等价于sendtime > NOW() - 2分钟。两种写法都可以,但注意方向不要搞反。
1.6 易错点与补充
| 易错点 | 说明 |
|---|---|
| 时间部分影响 | DATEDIFF 忽略时间,但 TIMESTAMPDIFF 可精确到秒,根据需要选择 |
| 加减单位单复数 | 单位统一用单数:DAY 而非 DAYS,MONTH 而非 MONTHS |
| NULL 值处理 | 任何包含 NULL 的日期运算结果均为 NULL |
| 时区问题 | NOW() 返回服务器时区时间,若需 UTC 可用 UTC_TIMESTAMP() |
补充常用函数:
TIMESTAMPDIFF(unit, datetime1, datetime2):返回datetime2 - datetime1的差值,单位可为SECOND、MINUTE、HOUR、DAY、MONTH、YEAR等。DATE_FORMAT(date, format):自定义格式化日期,如DATE_FORMAT(NOW(), '%Y年%m月%d日')。
sql
-- 示例:计算两个时间相差的分钟数
SELECT TIMESTAMPDIFF(MINUTE, '2026-06-17 14:00:00', '2026-06-17 14:32:00'); -- 32
2. 字符串函数
字符串函数在数据清洗、报表展示、字段拼接等场景中极为常用。
2.1 字符集与字节长度
CHARSET(str):返回字符串的字符集(如utf8mb4)LENGTH(str):返回字符串的字节长度(与字符集有关)CHAR_LENGTH(str):返回字符串的字符个数
sql
SELECT CHARSET('你好'); -- utf8mb4
SELECT LENGTH('你好'); -- 6 (utf8mb4 中每个汉字占 3 字节)
SELECT CHAR_LENGTH('你好'); -- 2
SELECT LENGTH('abc'); -- 3 (ASCII 每个字符 1 字节)
⚠️ 易错 :
LENGTH()返回的是字节数,不是字符数。如果使用utf8mb4,一个 emoji 表情占 4 字节,务必注意。
2.2 拼接与格式化
CONCAT(str1, str2, ...):拼接多个字符串CONCAT_WS(separator, str1, str2, ...):使用分隔符拼接(WS = With Separator)
sql
SELECT CONCAT('Hello', ' ', 'World'); -- Hello World
SELECT CONCAT_WS('-', '2026', '06', '17'); -- 2026-06-17
注意 :CONCAT 中若任一参数为 NULL,则整个结果为 NULL;而 CONCAT_WS 会跳过 NULL 值(但不会跳过分隔符)。
2.3 替换与截取
REPLACE(str, from_str, to_str):替换所有匹配的子串SUBSTRING(str, pos, length):从pos开始截取length个字符(pos从 1 开始)LEFT(str, n)/RIGHT(str, n):从左边/右边截取 n 个字符
sql
-- 替换
SELECT REPLACE('hello world', 'world', 'MySQL'); -- hello MySQL
-- 截取(从第2个字符开始取2个)
SELECT SUBSTRING('hello', 2, 2); -- el
SELECT SUBSTRING('hello', -2, 2); -- lo (负数表示从尾部开始)
2.4 大小写转换
UPPER(str)/LCASE(str)(或LOWER)
sql
SELECT UPPER('hello'); -- HELLO
SELECT LCASE('WORLD'); -- world
经典需求 :首字母小写,其余不变 ------ 结合 SUBSTRING 和 CONCAT。
2.5 经典案例:学生成绩单格式化
假设有成绩表 exam_result(字段:name, chinese, math, english),要求显示为 "XXX的语文是XX分,数学XX分,英语XX分"。
sql
SELECT CONCAT(name, '的语文是', chinese, '分,数学是', math, '分,英语是', english, '分')
AS 成绩描述
FROM exam_result;
进阶 :若某科成绩为 NULL,希望显示"缺考",可结合 IFNULL:
sql
SELECT CONCAT(name, '的语文是', IFNULL(chinese, '缺考'), '分,数学是', IFNULL(math, '缺考'), '分,英语是', IFNULL(english, '缺考'), '分')
FROM exam_result;
2.6 易错点与补充
| 易错点 | 说明 |
|---|---|
| 索引从 1 开始 | SUBSTRING 的 pos 从 1 开始,不同于编程语言(如 Java 从 0 开始) |
| NULL 拼接 | CONCAT 遇 NULL 返回 NULL,可用 CONCAT_WS 或 IFNULL 规避 |
| 字节 vs 字符 | 使用 LENGTH 注意编码,建议用 CHAR_LENGTH 统计字符数 |
| 替换大小写敏感 | REPLACE 区分大小写;若需不区分,可结合 LOWER/UPPER 处理 |
补充常用函数:
INSTR(str, substr):返回子串首次出现的位置(从 1 开始),不存在返回 0LTRIM/RTRIM/TRIM:去除空格REPEAT(str, count):重复字符串REVERSE(str):反转字符串
3. 数学函数
数学函数多用于数值计算、统计、进制转换等。
3.1 绝对值与取整
| 函数 | 说明 |
|---|---|
ABS(x) |
绝对值 |
CEILING(x) / CEIL(x) |
向上取整(返回不小于 x 的最小整数) |
FLOOR(x) |
向下取整(返回不大于 x 的最大整数) |
ROUND(x, d) |
四舍五入保留 d 位小数 |
TRUNCATE(x, d) |
截断保留 d 位小数(不四舍五入) |
sql
SELECT ABS(-5.2); -- 5.2
SELECT CEILING(5.2); -- 6
SELECT FLOOR(5.9); -- 5
SELECT ROUND(5.236, 2); -- 5.24
SELECT TRUNCATE(5.236, 2); -- 5.23
3.2 进制转换
BIN(decimal):转二进制字符串HEX(decimal):转十六进制字符串CONV(number, from_base, to_base):通用进制转换(结果以字符串形式返回)
sql
SELECT BIN(10); -- 1010
SELECT HEX(255); -- FF
SELECT CONV('1010', 2, 10); -- 10 (二进制转十进制)
SELECT CONV('FF', 16, 10); -- 255
3.3 随机数与格式化
RAND():返回[0.0, 1.0)的随机浮点数FORMAT(x, d):格式化数字,保留 d 位小数,并添加千位分隔符(注意返回的是字符串)
sql
SELECT RAND(); -- 0.123456789
SELECT RAND(100); -- 可指定种子,生成确定性随机序列
SELECT FORMAT(12345.6789, 2); -- '12,345.68'
⚠️
FORMAT返回字符串,且会添加逗号分隔符,若需纯数字格式,应使用ROUND或CAST。
3.4 易错点与补充
| 易错点 | 说明 |
|---|---|
| 取整方向 | CEILING 向正无穷取整,FLOOR 向负无穷取整,对于负数需留意:CEILING(-5.2) = -5,FLOOR(-5.2) = -6 |
| 随机数重复 | 不指定种子时,每次执行结果不同;指定种子后,相同种子产生相同序列 |
| 格式化陷阱 | FORMAT 返回字符串且带逗号,若参与数值运算需先转换回数字(CAST 或 +0) |
补充 :取模运算 MOD(n, m),等价于 % 操作符。
4. 其他常用函数
4.1 用户与数据库信息
USER()/CURRENT_USER():当前连接的用户名DATABASE():当前使用的数据库名VERSION():MySQL 版本号
sql
SELECT USER(); -- root@localhost
SELECT DATABASE(); -- test_db
SELECT VERSION(); -- 8.0.33
4.2 加密与摘要
MD5(str):返回 32 位十六进制 MD5 摘要SHA1(str)/SHA2(str, hash_length):更安全的哈希算法PASSWORD(str):MySQL 原生密码加密(已废弃,不推荐使用)
sql
SELECT MD5('admin'); -- 21232f297a57a5a743894a0e4a801fc3
SELECT SHA1('admin'); -- d033e22ae348aeb5660fc2140aec35850c4da997
🔐 提示:
PASSWORD()在 MySQL 8.0 中已弃用,建议使用SHA2或应用层加密。
4.3 空值处理
IFNULL(expr1, expr2):若expr1为NULL,返回expr2,否则返回expr1COALESCE(expr1, expr2, ..., exprn):返回第一个非NULL的值(更通用)
sql
SELECT IFNULL(NULL, 'default'); -- default
SELECT IFNULL('abc', 'default'); -- abc
SELECT COALESCE(NULL, NULL, 'first_non_null', 'last'); -- first_non_null
4.4 条件判断(补充)
IF(condition, true_val, false_val):类似三元运算符CASE WHEN ... THEN ... END:更复杂的条件分支
sql
-- IF 示例
SELECT IF(1 > 2, '大于', '不大于'); -- 不大于
-- CASE 示例(常用于统计)
SELECT name,
CASE
WHEN score >= 90 THEN '优秀'
WHEN score >= 60 THEN '及格'
ELSE '不及格'
END AS grade
FROM student;
5. 实战 OJ 演练
题目 :查找字符串
'10,A,B'中逗号','出现的次数。
解题思路:计算原字符串长度与去除逗号后长度的差值,即为逗号个数。
sql
SELECT LENGTH('10,A,B') - LENGTH(REPLACE('10,A,B', ',', '')) AS cnt;
解析:
LENGTH('10,A,B')返回字节长度(此处均为单字节,数值等于字符数)REPLACE('10,A,B', ',', '')将逗号替换为空,得到'10AB'- 两者长度之差即为逗号数量
扩展 :若字符串包含多字节字符,建议使用 CHAR_LENGTH 而非 LENGTH,以确保字符计数准确。
6. 总结与建议
| 函数类别 | 核心要点 |
|---|---|
| 日期函数 | 关注时区、NULL 处理、DATEDIFF 只算天数;多用 TIMESTAMPDIFF 获取精确差值 |
| 字符串函数 | 区分字节与字符长度;CONCAT 遇 NULL 易失效;SUBSTRING 索引从 1 开始 |
| 数学函数 | 注意取整方向(正负无穷);FORMAT 返回字符串,谨慎用于计算 |
| 其他函数 | IFNULL 和 COALESCE 是处理 NULL 的利器;MD5 不可逆,适用于密码摘要 |
学习建议:
- 多做练习,结合
SELECT语句实时验证函数结果。 - 阅读官方文档,熟悉每个函数的边界条件(如参数类型、溢出情况)。
- 善用
EXPLAIN观察函数是否影响索引使用(例如在WHERE中对列使用函数可能使索引失效)。
希望本文能帮助你全面掌握 MySQL 内置函数,并在实际开发中游刃有余。如果觉得有用,欢迎点赞收藏,也欢迎在评论区交流你的使用心得与疑惑!🚀