做后端开发这些年,MySQL函数是那种“用得越频繁反而越容易被忽视”的东西。平时写SELECT时顺手用一下NOW()、ROUND(),觉得没什么技术含量,可真到了面试、报表统计、复杂业务查询的时候,能不能把函数用对、用活,直接就分出高下了。这篇文章把我这些年实际项目里用过、踩过坑的MySQL函数做一次完整梳理,从最常用的字符串、日期、条件函数,到聚合函数和窗口函数,再聊到自定义函数与存储过程的边界问题,最后补充几道高频面试题的思路和一套新手练习环境准备。适合刚上手MySQL的初学者,也适合想系统复习函数知识的开发者。
1. 函数在MySQL里到底有多重要
1.1 函数不是语法糖,而是SQL表达能力的分水岭
很多人一开始写SQL,只会SELECT、WHERE、GROUP BY,遇到“用户名要拼接”“日期要格式化”“空值要兜底”这些需求,第一反应是拉出来到程序里用Java、Python处理。这个习惯本身没错,但会造成两个问题:一是程序里写一堆循环和判断,代码又长又难维护;二是明明一条SQL能算完的数据,非要全表捞到应用层,网络开销和内存占用全都上去了。
MySQL函数解决的就是“在数据库内部完成加工和计算”这件事。比如一张订单表,要按月份统计每个用户的订单数和总金额,如果不用函数,你得把所有订单查出来,自己遍历分组;用了DATE_FORMAT和聚合函数,一条SQL直接出结果。再比如查询时某个字段可能为NULL,页面要显示“未知”,用IFNULL或COALESCE就能在SQL层面完成兜底,程序里少写一堆判空逻辑。
从面试角度来说,函数也是MySQL考察的高频区,像count(*)、count(1)、count(字段)三者区别、GROUP BY和HAVING的执行顺序、为什么对索引字段用函数会导致全表扫描,这些问题几乎每次面试都能遇到几个。所以函数不只是“会用就行”,而是理解数据库查询底层逻辑的重要入口。我从自己的学习路径和带新人经验来看,函数是性价比极高的一块内容:投入产出比高、即学即用、对排查线上慢查询也很有帮助。
1.2 函数分类全景:一张表看懂该去哪查哪种函数
MySQL函数数量非常多,但常用的大致可以分成六类。刚开始接触的人不用急着把所有函数都背下来,先知道分类,知道“某个需求该去哪个分类里找函数”,遇到具体场景再查手册,效率会高很多。
| 函数分类 | 典型函数举例 | 实际业务场景 |
|---|---|---|
| 字符串函数 | CONCAT、SUBSTRING_INDEX、REPLACE、TRIM | 姓名拼接、截取订单号、清洗脏数据 |
| 数值函数 | ROUND、CEIL、FLOOR、MOD、SQRT | 金额四舍五入、库存取整、余数分配 |
| 日期时间函数 | NOW、DATE_FORMAT、DATEDIFF、TIMESTAMPDIFF | 报表按月统计、计算年龄和工龄 |
| 条件函数 | IF、IFNULL、COALESCE、CASE WHEN | 空值兜底、逻辑分支转换 |
| 聚合函数 | COUNT、SUM、AVG、MAX、MIN、GROUP_CONCAT | 分组统计、汇总报表 |
| 窗口函数 | ROW_NUMBER、RANK、DENSE_RANK、SUM OVER | 分组排名、同比环比、TopN |
注意,这个表只覆盖了开发中最常用的部分。MySQL还有JSON函数、加密函数、流程控制函数等,等基础打牢之后按需扩充就行。我的习惯是:在Navicat或Workbench里打开函数列表,把不认识的函数名扫一眼,至少知道它是干什么的,真到用的时候再去查详细语法。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 字符串与数值函数:最高频的“基础操作”
2.1 字符串函数:拼接、截取、替换、去空格
字符串函数是日常开发里使用频率最高的,我几乎每天都会写。先看几个必须掌握的。
CONCAT(col1, col2, ...):把多个字符串拼接成一个。比如用户表里分别存了姓氏和名字,要显示完整姓名,可以写SELECT CONCAT(last_name, first_name) FROM user;。这里有一个特别容易踩的坑:CONCAT只要有一个参数是NULL,整个结果就是NULL。我早期就因为这个原因线上出现过“用户名为空”的Bug,排查了半天发现是中间名存了NULL。解决办法是用CONCAT_WS或者先IFNULL处理:
sql复制SELECT CONCAT_WS(' ', first_name, last_name) FROM user;
-- CONCAT_WS第一个参数是分隔符,遇到NULL会跳过而不是整条变NULL
SUBSTRING_INDEX(str, delimiter, count):按分隔符截取字符串,这个函数非常好用。它的逻辑是“在第count个分隔符的地方切开”,count为正数时从左边开始数,为负数时从右边开始数。比如有一个字段存的是"北京市-朝阳区-望京街道",想取城市名:
sql复制SELECT SUBSTRING_INDEX(addr, '-', 1); -- 北京市
SELECT SUBSTRING_INDEX(addr, '-', -1); -- 望京街道
REPLACE(str, from_str, to_str):全局替换字符串。比如电话号码脱敏,把中间四位换成星号:
sql复制SELECT REPLACE(phone, SUBSTRING(phone, 4, 4), '****') FROM user;
TRIM、LTRIM、RTRIM:去掉字符串两边的空格。我经常在处理Excel导入的数据时用TRIM,因为用户手动填的表格里经常带着肉眼看不见的空格,直接查会查不到。
提示:字符串函数在与索引配合时需要特别注意。比如
WHERE LEFT(name, 2) = '张',虽然结果是对的,但无法使用name字段上的索引;改成WHERE name LIKE '张%'才能真正用上索引。
2.2 数值函数:四舍五入、取整、取余、开方
数值函数的场景相对简单,但细节也不少。ROUND用于四舍五入,可以带精度参数;CEIL向上取整,FLOOR向下取整;MOD取余数;SQRT求平方根。
我实际项目里遇到最多的组合是分页和金额计算。比如订单金额price * quantity计算出的小数位特别多,要保留两位小数:
sql复制SELECT ROUND(price * quantity, 2) FROM order_detail;
这里要注意ROUND与TRUNCATE的区别:ROUND是四舍五入,TRUNCATE是直接截断。同样是123.456,`R
