MySQL 常用内置函数讲解

掌握 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 数值 单位)

单位支持:YEARMONTHDAYHOURMINUTESECONDWEEKQUARTER 等。

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_ADDDATE_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,包含 idcontentsendtime(DATETIME)。要求:

  1. 显示所有留言,但只显示日期(不显示时间)
  2. 查询最近 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 而非 DAYSMONTH 而非 MONTHS
NULL 值处理 任何包含 NULL 的日期运算结果均为 NULL
时区问题 NOW() 返回服务器时区时间,若需 UTC 可用 UTC_TIMESTAMP()

补充常用函数

  • TIMESTAMPDIFF(unit, datetime1, datetime2):返回 datetime2 - datetime1 的差值,单位可为 SECONDMINUTEHOURDAYMONTHYEAR 等。
  • 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

经典需求 :首字母小写,其余不变 ------ 结合 SUBSTRINGCONCAT

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 开始 SUBSTRINGpos 从 1 开始,不同于编程语言(如 Java 从 0 开始)
NULL 拼接 CONCATNULL 返回 NULL,可用 CONCAT_WSIFNULL 规避
字节 vs 字符 使用 LENGTH 注意编码,建议用 CHAR_LENGTH 统计字符数
替换大小写敏感 REPLACE 区分大小写;若需不区分,可结合 LOWER/UPPER 处理

补充常用函数

  • INSTR(str, substr):返回子串首次出现的位置(从 1 开始),不存在返回 0
  • LTRIM / 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 返回字符串,且会添加逗号分隔符,若需纯数字格式,应使用 ROUNDCAST

3.4 易错点与补充

易错点 说明
取整方向 CEILING 向正无穷取整,FLOOR 向负无穷取整,对于负数需留意:CEILING(-5.2) = -5FLOOR(-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):若 expr1NULL,返回 expr2,否则返回 expr1
  • COALESCE(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 获取精确差值
字符串函数 区分字节与字符长度;CONCATNULL 易失效;SUBSTRING 索引从 1 开始
数学函数 注意取整方向(正负无穷);FORMAT 返回字符串,谨慎用于计算
其他函数 IFNULLCOALESCE 是处理 NULL 的利器;MD5 不可逆,适用于密码摘要

学习建议

  • 多做练习,结合 SELECT 语句实时验证函数结果。
  • 阅读官方文档,熟悉每个函数的边界条件(如参数类型、溢出情况)。
  • 善用 EXPLAIN 观察函数是否影响索引使用(例如在 WHERE 中对列使用函数可能使索引失效)。

希望本文能帮助你全面掌握 MySQL 内置函数,并在实际开发中游刃有余。如果觉得有用,欢迎点赞收藏,也欢迎在评论区交流你的使用心得与疑惑!🚀

参考文档MySQL 8.0 Reference Manual - Built-in Functions