MySQL: MySQL内置函数大全与实战应用
最后更新:2026-08-26
函数是 SQL 的瑞士军刀——数据转换、格式化、计算都靠它。
本课系统讲解 MySQL 最常用的内置函数。
graph TB
A[MySQL 内置函数] --> B[数学函数<br/>ROUND/CEIL/FLOOR/RAND]
A --> C[字符串函数<br/>CONCAT/LENGTH/SUBSTRING]
A --> D[日期函数<br/>NOW/DATE_FORMAT/DATEDIFF]
A --> E[条件函数<br/>IF/IFNULL/CASE]
A --> F[聚合函数<br/>COUNT/SUM/AVG/MAX/MIN]
A --> G[类型转换<br/>CAST/CONVERT]
1. 你将学到
- 数学函数(ROUND/CEIL/FLOOR/MOD)
- 字符串函数(CONCAT/LENGTH/SUBSTRING/REPLACE)
- 日期函数(NOW/DATE_FORMAT/DATEDIFF/DATE_ADD)
- 类型转换函数(CAST/CONVERT)
- 条件函数(IF/IFNULL/CASE)
2. 数据清洗的真实故事
(1) 痛点:数据格式混乱
用户注册数据:
| name | phone | created_at |
|---|---|---|
| John | 138-0000-1111 | 2026/07/03 |
| Jane | 13800002222 | 03-07-2026 |
电话号码格式不统一,日期格式混乱。
(2) 函数的解法
SQL
-- 统一电话格式
SELECT name, REPLACE(phone, '-', '') AS clean_phone FROM users;
-- 统一日期格式
SELECT name, STR_TO_DATE(created_at, '%Y/%m/%d') AS clean_date FROM users;
3. 数学函数
| 函数 | 说明 | 示例 |
|---|---|---|
ROUND(x, d) |
四舍五入 | ROUND(3.1415, 2) → 3.14 |
CEIL(x) |
向上取整 | CEIL(3.1) → 4 |
FLOOR(x) |
向下取整 | FLOOR(3.9) → 3 |
ABS(x) |
绝对值 | ABS(-5) → 5 |
MOD(a, b) |
取余 | MOD(10, 3) → 1 |
POWER(x, y) |
幂运算 | POWER(2, 3) → 8 |
SQRT(x) |
平方根 | SQRT(16) → 4 |
RAND() |
随机数 0~1 | RAND() → 0.723... |
▶ 示例:数学函数应用
SQL
-- 计算折扣价并四舍五入
SELECT
product_name,
price,
ROUND(price * 0.85, 2) AS sale_price
FROM products;
-- 计算页数(向上取整)
SELECT CEIL(103 / 10) AS total_pages; -- 11 页
-- 随机排序
SELECT * FROM users ORDER BY RAND() LIMIT 5;
4. 字符串函数
| 函数 | 说明 | 示例 |
|---|---|---|
CONCAT(s1, s2, ...) |
拼接字符串 | CONCAT('Hello', ' ', 'World') |
CONCAT_WS(sep, s1, ...) |
用分隔符拼接 | CONCAT_WS('-', '2026', '07', '03') |
LENGTH(s) |
字节长度 | LENGTH('Hello') → 5 |
CHAR_LENGTH(s) |
字符长度 | CHAR_LENGTH('你好') → 2 |
UPPER(s) |
转大写 | UPPER('hello') → HELLO |
LOWER(s) |
转小写 | LOWER('HELLO') → hello |
TRIM(s) |
去除首尾空格 | TRIM(' hi ') → hi |
LTRIM(s) |
去除左侧空格 | LTRIM(' hi') → hi |
RTRIM(s) |
去除右侧空格 | RTRIM('hi ') → hi |
SUBSTRING(s, pos, len) |
截取子串 | SUBSTRING('Hello', 2, 3) → ell |
LEFT(s, n) |
左侧 n 个字符 | LEFT('Hello', 3) → Hel |
RIGHT(s, n) |
右侧 n 个字符 | RIGHT('Hello', 3) → llo |
REPLACE(s, old, new) |
替换 | REPLACE('Hi World', 'Hi', 'Hello') |
REVERSE(s) |
反转 | REVERSE('Hello') → olleH |
LPAD(s, len, pad) |
左填充 | LPAD('5', 3, '0') → 005 |
RPAD(s, len, pad) |
右填充 | RPAD('Hi', 5, '.') → Hi... |
▶ 示例:字符串函数应用
SQL
-- 拼接全名
SELECT CONCAT(first_name, ' ', last_name) AS full_name FROM employees;
-- 清理电话号码
SELECT REPLACE(REPLACE(phone, '-', ''), ' ', '') AS clean_phone FROM users;
-- 截取邮箱域名
SELECT
email,
SUBSTRING(email, LOCATE('@', email) + 1) AS domain
FROM users;
-- 生成订单号
SELECT CONCAT('ORD', LPAD(id, 6, '0')) AS order_no FROM orders;
输出:
TEXT
📖 仅展示
+-------------+------------+
| email | domain |
+-------------+------------+
| a@gmail.com | gmail.com |
| b@163.com | 163.com |
+-------------+------------+
5. 日期函数
| 函数 | 说明 | 示例 |
|---|---|---|
NOW() |
当前日期时间 | 2026-07-03 10:30:00 |
CURDATE() |
当前日期 | 2026-07-03 |
CURTIME() |
当前时间 | 10:30:00 |
DATE(dt) |
提取日期部分 | DATE('2026-07-03 10:30:00') |
YEAR(dt) |
提取年份 | YEAR('2026-07-03') → 2026 |
MONTH(dt) |
提取月份 | MONTH('2026-07-03') → 7 |
DAY(dt) |
提取日 | DAY('2026-07-03') → 3 |
HOUR(dt) |
提取小时 | HOUR('10:30:00') → 10 |
DATE_FORMAT(dt, fmt) |
格式化日期 | DATE_FORMAT(NOW(), '%Y年%m月%d日') |
STR_TO_DATE(s, fmt) |
字符串转日期 | STR_TO_DATE('2026-07-03', '%Y-%m-%d') |
DATEDIFF(d1, d2) |
日期差(天) | DATEDIFF('2026-07-10', '2026-07-03') → 7 |
DATE_ADD(dt, INTERVAL) |
日期加 | DATE_ADD(NOW(), INTERVAL 7 DAY) |
DATE_SUB(dt, INTERVAL) |
日期减 | DATE_SUB(NOW(), INTERVAL 1 MONTH) |
TIMESTAMPDIFF(unit, d1, d2) |
时间差 | TIMESTAMPDIFF(YEAR, birth, CURDATE()) |
▶ 示例:日期函数应用
SQL
-- 查询今天的数据
SELECT * FROM orders WHERE DATE(created_at) = CURDATE();
-- 查询最近 7 天
SELECT * FROM orders WHERE created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY);
-- 按月统计
SELECT
DATE_FORMAT(order_date, '%Y-%m') AS month,
COUNT(*) AS order_count,
SUM(amount) AS total_amount
FROM orders
GROUP BY month
ORDER BY month;
-- 计算年龄
SELECT
name,
birth_date,
TIMESTAMPDIFF(YEAR, birth_date, CURDATE()) AS age
FROM users;
输出:
TEXT
📖 仅展示
+---------+-------------+--------------+
| month | order_count | total_amount |
+---------+-------------+--------------+
| 2026-01 | 120 | 45000.00 |
| 2026-02 | 135 | 52000.00 |
| 2026-03 | 148 | 58000.00 |
+---------+-------------+--------------+
▶ 示例:日期格式化
SQL
-- 常用格式
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d'); -- 2026-07-03
SELECT DATE_FORMAT(NOW(), '%Y年%m月%d日'); -- 2026年07月03日
SELECT DATE_FORMAT(NOW(), '%H:%i:%s'); -- 10:30:00
SELECT DATE_FORMAT(NOW(), '%W, %M %d, %Y'); -- Friday, July 03, 2026
6. 条件函数
| 函数 | 说明 | 示例 |
|---|---|---|
IF(expr, t, f) |
条件判断 | IF(score >= 60, 'Pass', 'Fail') |
IFNULL(expr, alt) |
NULL 替换 | IFNULL(email, 'N/A') |
NULLIF(a, b) |
相等返回 NULL | NULLIF(1, 1) → NULL |
CASE WHEN ... THEN ... END |
多条件判断 | 见示例 |
▶ 示例:条件函数
SQL
-- IF 判断
SELECT
name,
score,
IF(score >= 60, 'Pass', 'Fail') AS result
FROM students;
-- IFNULL 处理 NULL
SELECT
name,
IFNULL(phone, 'No phone') AS phone
FROM users;
-- CASE 多条件
SELECT
name,
score,
CASE
WHEN score >= 90 THEN 'A'
WHEN score >= 80 THEN 'B'
WHEN score >= 70 THEN 'C'
WHEN score >= 60 THEN 'D'
ELSE 'F'
END AS grade
FROM students;
输出:
TEXT
📖 仅展示
+-------+-------+-------+
| name | score | grade |
+-------+-------+-------+
| Alice | 95 | A |
| Bob | 82 | B |
| Carol | 67 | D |
| Dave | 45 | F |
+-------+-------+-------+
7. 聚合函数预览
| 函数 | 说明 | 示例 |
|---|---|---|
COUNT(*) |
计数 | SELECT COUNT(*) FROM users |
SUM(col) |
求和 | SELECT SUM(amount) FROM orders |
AVG(col) |
平均值 | SELECT AVG(salary) FROM employees |
MAX(col) |
最大值 | SELECT MAX(price) FROM products |
MIN(col) |
最小值 | SELECT MIN(age) FROM users |
详见第 12 课 聚合与分组。
❓ 常见问题
Q CONCAT 中有 NULL 结果是什么?
A 结果为 NULL。用
CONCAT_WS 或 IFNULL 处理:CONCAT_WS(' ', 'Hello', NULL) → 'Hello'。Q NOW() 和 CURDATE() 区别?
A NOW() 返回日期+时间,CURDATE() 只返回日期。
Q 日期格式化符号在哪查?
A 搜索 "MySQL DATE_FORMAT specifiers",常用:%Y(年) %m(月) %d(日) %H(时) %i(分) %s(秒)。
Q 函数能用在 WHERE 中吗?
A 可以,但会影响索引。
WHERE DATE(created_at) = CURDATE() 无法走索引,改用范围:WHERE created_at >= CURDATE() AND created_at < CURDATE() + 1。📖 小节
- 数学函数:ROUND/CEIL/FLOOR/MOD/RAND
- 字符串函数:CONCAT/LENGTH/UPPER/LOWER/TRIM/SUBSTRING/REPLACE
- 日期函数:NOW/CURDATE/DATE_FORMAT/DATEDIFF/DATE_ADD/DATE_SUB
- 条件函数:IF/IFNULL/CASE WHEN
- 聚合函数:COUNT/SUM/AVG/MAX/MIN
📝 作业
-
基础题(难度⭐):用 CONCAT 和 LPAD 生成订单号 'ORD000001' 格式。
-
进阶题(难度⭐⭐):查询最近 30 天每天的订单数量,用 DATE_FORMAT 格式化日期。
-
挑战题(难度⭐⭐⭐):计算每个用户的年龄,并用 CASE WHEN 分为 '少年/青年/中年/老年' 四个等级。