欢迎光临
我们一直在努力

三、MySQL函数

一、什么是函数

你可以把函数想象成 MySQL 内置的“加工厂”或“小工具”。它是预先定义好的代码逻辑,你只需要把原始数据(参数)丢进去,它就会按照设定的规则进行处理,然后返回一个结果。这就像榨汁机,你放进去水果(参数),它就能榨出果汁(返回值),省去了你自己动手切水果的麻烦。

使用函数的主要优势:

  • 提升效率:将复杂计算逻辑封装在数据库层执行,减少应用层代码量。
  • 保证一致性:相同的业务规则(如日期格式化、金额舍入)在 SQL 中统一处理,避免不同应用实现不一致。
  • 简化查询:让 SQL 语句更清晰、更易读。

二、函数的分类

按照功能,MySQL 的内置函数主要分为以下几大类:

类别主要功能典型应用场景
字符串函数 处理文本数据(拼接、截取、替换、大小写转换等) 数据清洗、格式化展示、敏感信息脱敏
数值函数 执行数学计算(四舍五入、取整、求绝对值、取模等) 价格计算、分页统计、数值校验
日期函数 处理时间和日期(获取当前时间、计算差值、提取部分等) 会员有效期、活动倒计时、按时间维度统计
流程控制函数 实现条件判断(类似编程中的 if-else, switch-case) 数据状态翻译、空值兜底、条件赋值
聚合函数 对多行数据进行统计(求和、平均、计数、最大/最小值) 数据报表、分组统计、数据分析

1. 字符串函数

字符串函数是日常开发中最常用的,主要用于数据清洗、格式化展示等场景。

2. 数值函数

数值函数用于直接在查询中执行数学计算,提升效率,避免把数据取出来再用后端代码计算。

3. 日期函数

日期函数是构建时效性业务(如会员有效期、活动倒计时、报表统计)的基石。

4. 流程控制函数

这类函数赋予了 SQL 强大的分支逻辑表达能力,让你可以在查询时直接根据条件返回不同的结果,避免在应用层写大量的 if-else。

5. 聚合函数

聚合函数通常与 GROUP BY 搭配使用,用来对多行数据进行统计。它是生成各种数据报表的核心。

三、字符串函数

字符串函数是日常开发中最常用的,主要用于数据清洗、格式化展示等场景。

1. CONCAT(str1, str2, …):拼接字符串。

场景说明:在电商系统中,我们通常会把用户的“姓”和“名”分开存储,但在前端展示时需要连在一起。

— 示例
SELECT CONCAT('张', '三');
— 返回:张三

— 实际表查询示例
SELECT CONCAT(last_name, first_name) AS full_name FROM users;

2. SUBSTRING(str, start, len):截取子串。

场景说明:处理身份证号或手机号时,出于隐私保护,我们可能需要截取部分字符进行脱敏显示。

— 示例:截取手机号前3位
SELECT SUBSTRING('13812345678', 1, 3);
— 返回:138

— 示例:身份证号脱敏,显示前6位和后4位
SELECT CONCAT(SUBSTRING(id_card, 1, 6), '****', SUBSTRING(id_card, 4)) AS masked_id FROM customers;

3. REPLACE(str, from_str, to_str):替换字符串。

场景说明:用户输入的评论中可能包含敏感词,我们需要将其替换为星号。

— 示例
SELECT REPLACE('你好傻瓜', '傻瓜', '**');
— 返回:你好**

— 实际应用:批量更新评论中的敏感词
UPDATE comments SET content = REPLACE(content, '敏感词', '***');

4. TRIM(str):去除首尾空格。

场景说明:用户在注册时输入用户名,可能不小心多打了空格,用 TRIM 可以清洗数据。

— 示例
SELECT TRIM(' hello ');
— 返回:hello

— 插入数据时自动清洗
INSERT INTO users (username) VALUES (TRIM(' new_user '));

其他常用字符串函数速查:

  • LENGTH(str) / CHAR_LENGTH(str):返回字符串的字节长度 / 字符长度。
  • UPPER(str) / LOWER(str):将字符串转换为大写 / 小写。
  • LEFT(str, len) / RIGHT(str, len):从左边 / 右边开始截取指定长度的字符串。
  • LOCATE(substr, str):返回子串在字符串中第一次出现的位置。

四、数值函数

数值函数用于直接在查询中执行数学计算,提升效率,避免把数据取出来再用后端代码计算。

1. ROUND(x, d):四舍五入,保留 d 位小数。

场景说明:计算商品打折后的价格,财务上通常只保留两位小数。

— 示例
SELECT ROUND(99.876, 2);
— 返回:99.88

— 实际计算商品折后价
SELECT product_name, price, ROUND(price * 0.88, 2) AS discounted_price FROM products;

2. CEIL(x) / FLOOR(x):向上取整 / 向下取整。

场景说明:做分页功能时,计算总页数。比如 11 条数据,每页 10 条,总页数应该是 2 页,这就需要向上取整。

— 示例:计算总页数
SELECT CEIL(11 / 10);
— 返回:2

— 示例:价格按“百”向上取整报价
SELECT product_name, price, CEIL(price / 100) * 100 AS quoted_price FROM products;

3. ABS(x):求绝对值。

场景说明:计算两个温度之间的温差,结果不应为负数。

— 示例
SELECT ABS(10);
— 返回:10

— 计算温度波动范围
SELECT MAX(temp) MIN(temp) AS temp_range, ABS(MAX(temp) MIN(temp)) AS abs_range FROM temperature_log;

4. MOD(x, y):求余数(取模)。

场景说明:判断一个订单号是奇数还是偶数,或者用于数据库分库分表的哈希路由。

— 示例
SELECT MOD(10, 3);
— 返回:1

— 判断订单奇偶性
SELECT order_id, IF(MOD(order_id, 2) = 0, '偶数订单', '奇数订单') AS parity FROM orders;

其他常用数值函数速查:

  • POW(x, y) / SQRT(x):求 x 的 y 次幂 / 求平方根。
  • RAND():返回一个 0 到 1 之间的随机浮点数。
  • SIGN(x):返回参数的符号(正数返回1,负数返回-1,0返回0)。

五、日期函数

日期函数是构建时效性业务(如会员有效期、活动倒计时、报表统计)的基石。

1. NOW() / CURDATE():获取当前日期和时间 / 仅获取当前日期。

场景说明:用户下单时,系统需要记录精确的下单时间。

— 示例
SELECT NOW();
— 返回:2026-08-06 14:45:36

SELECT CURDATE();
— 返回:2026-08-06

— 插入当前时间戳
INSERT INTO orders (user_id, product_id, created_at) VALUES (1001, 2001, NOW());

2. DATEDIFF(date1, date2):计算两个日期相差的天数。

场景说明:计算员工的工龄,或者计算订单距离超时还剩多少天。

— 示例
SELECT DATEDIFF('2026-08-06', '2026-08-01');
— 返回:5

— 计算会员剩余有效期(天)
SELECT user_id, DATEDIFF(expiry_date, CURDATE()) AS days_left FROM memberships WHERE days_left > 0;

3. DATE_ADD(date, INTERVAL num unit):给日期增加时间间隔。

场景说明:用户购买了 30 天的 VIP 会员,需要计算会员的到期时间。

— 示例
SELECT DATE_ADD('2026-08-06', INTERVAL 30 DAY);
— 返回:2026-09-05

— 计算订单预计送达时间(3个工作日后)
SELECT order_id, DATE_ADD(order_date, INTERVAL 3 DAY) AS estimated_delivery FROM orders;

常用时间单位:YEAR, MONTH, DAY, HOUR, MINUTE, SECOND。

4. YEAR(date) / MONTH(date) / DAY(date):提取年/月/日。

场景说明:生成年度销售报表时,需要按年份对数据进行分组统计。

— 示例
SELECT YEAR('2026-08-06');
— 返回:2026

— 按年份统计销售额
SELECT YEAR(order_date) AS order_year, SUM(amount) AS total_sales FROM orders GROUP BY order_year;

其他常用日期函数速查:

  • CURTIME():返回当前时间。
  • DATE_SUB(date, INTERVAL expr unit):从日期减去指定的时间间隔。
  • DAYNAME(date) / MONTHNAME(date):返回日期的星期名 / 月份名。
  • WEEK(date):返回日期是一年中的第几周。

六、流程控制函数

这类函数赋予了 SQL 强大的分支逻辑表达能力,让你可以在查询时直接根据条件返回不同的结果,避免在应用层写大量的 if-else。

1. IF(condition, val1, val2):简单的条件判断(类似三元运算符)。

场景说明:查询学生成绩时,大于等于 60 分显示“及格”,否则显示“不及格”。

— 示例
SELECT IF(85 >= 60, '及格', '不及格');
— 返回:及格

— 实际查询学生成绩表
SELECT student_name, score, IF(score >= 60, '及格', '不及格') AS result FROM exam_scores;

2. IFNULL(val1, val2):空值处理。

场景说明:用户的“昵称”字段可能为空,展示时如果为空,就显示默认值“匿名用户”。

— 示例
SELECT IFNULL(NULL, '匿名用户');
— 返回:匿名用户

— 查询用户信息,处理空昵称
SELECT user_id, IFNULL(nickname, '匿名用户') AS display_name FROM users;

3. CASE WHEN … THEN … ELSE … END:多条件分支判断(类似 switch-case)。

场景说明:根据订单状态码(0, 1, 2)翻译成人类可读的文字(待支付, 已发货, 已完成)。

— 示例
SELECT
CASE
WHEN 1 = 1 THEN '待支付'
WHEN 1 = 2 THEN '已发货'
ELSE '未知状态'
END;
— 返回:待支付

— 实际订单状态翻译
SELECT order_id,
CASE status
WHEN 0 THEN '待支付'
WHEN 1 THEN '已发货'
WHEN 2 THEN '已完成'
WHEN 3 THEN '已取消'
ELSE '状态异常'
END AS status_text
FROM orders;

七、聚合函数

聚合函数通常与 GROUP BY 搭配使用,用来对多行数据进行统计。它是生成各种数据报表的核心。

1. COUNT(*) / COUNT(列名):统计行数。

场景说明:统计网站今天的总访问量,或者统计某个部门有多少名员工。

— 示例:统计总用户数
SELECT COUNT(*) FROM users;
— 返回:表中的总行数

— 统计特定部门的员工数(忽略 NULL)
SELECT COUNT(employee_id) FROM employees WHERE department = '技术部';

— 统计今日独立访客
SELECT COUNT(DISTINCT user_id) FROM site_visits WHERE visit_date = CURDATE();

2. SUM(列名):求和。

场景说明:计算某个用户所有订单的总消费金额。

— 示例:计算用户 1001 的总消费
SELECT SUM(price) FROM orders WHERE user_id = 1001;
— 返回:该用户的总花费

— 按月份统计销售总额
SELECT MONTH(order_date) AS month, SUM(amount) AS monthly_sales FROM orders GROUP BY month;

3. AVG(列名):求平均值。

场景说明:计算全班同学的数学平均成绩。

— 示例
SELECT AVG(score) FROM scores WHERE subject = '数学';
— 返回:平均分

— 计算每个产品的平均评分
SELECT product_id, AVG(rating) AS avg_rating FROM product_reviews GROUP BY product_id;

4. MAX(列名) / MIN(列名):求最大值 / 最小值。

场景说明:找出公司里薪资最高和最低的员工,或者找出商品库里的最高价和最低价。

— 示例:找出最高薪资
SELECT MAX(salary) FROM employees;
— 返回:最高薪资

— 找出每个品类的最低价商品
SELECT category, MIN(price) AS lowest_price FROM products GROUP BY category;

八、注意事项

在实际开发中,尽量避免在 WHERE 子句中对字段使用函数(例如 WHERE YEAR(create_time) = 2026),这会导致该字段的索引失效,引发全表扫描,严重影响查询性能。尽量改写为范围查询,如 create_time BETWEEN '2026-01-01' AND '2026-12-31'。

性能影响原理对比:

查询方式索引使用情况性能影响
WHERE YEAR(create_time) = 2026 索引失效 全表扫描,慢
WHERE create_time BETWEEN '2026-01-01' AND '2026-12-31' 可以使用索引 范围查询,快

原因分析:
如果不用函数:你查 create_time = '2026-05-01',MySQL 知道 create_time 字段是排好序的,它可以直接去索引树里精准定位。

如果用了函数:MySQL 的索引里存的只是 create_time 的原始值(比如 2026-05-01 14:30:00),并没有存 YEAR(create_time) 计算后的结果。MySQL 没办法直接去索引里找,只能被迫把表里的每一行数据都拿出来,挨个计算 YEAR(create_time),看看是不是等于 2026。这个“挨个拿出来计算”的过程,就是全表扫描。当你的表里有 100 万条数据时,这个计算过程会极其缓慢,严重拖垮系统性能。

最佳实践建议:

  • 将函数计算移到等号右侧:对常量或参数使用函数,而不是对字段使用函数。
  • 使用范围查询替代:如上例所示,用 BETWEEN 或 >=、<= 来利用索引。
  • 考虑生成计算列:对于频繁使用的函数计算(如 YEAR(create_time)),可以在表中新增一个持久化的计算列并为其建立索引(MySQL 5.7+ 支持生成列)。
  • 赞(0)
    未经允许不得转载:171主机测评 » 三、MySQL函数
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址