你刚开始学 MySQL 的时候,是不是经常在 SQL 里看到 NOW()、COUNT(*)、IFNULL() 这种写法,别人告诉你“这是函数”,好像听懂了,但真到自己写的时候又不知道选哪个。这篇我就以 MySQL 数据库基础里的函数为主线,把最常用的几类函数掰开揉碎讲一遍,不只是列语法,还会告诉你每个函数在真实业务里怎么用、有哪些容易踩的坑。
我会用同一张员工表贯穿全文,从字符串处理、数值计算、日期时间统计,到条件判断、聚合和行转列,再到自定义函数和常见报错,让你学完就能直接在本地库上跑起来。内容同样适合准备 MySQL 面试的人,后半部分我会把面试里高频出现的函数考点和易错场景做一次集中梳理。
1. 先搞懂 MySQL 函数是什么,再开始写 SQL
1.1 为什么函数是 MySQL 基础里最绕不开的一块
函数本质上是一段封装好的处理逻辑,它接收一个或多个输入值,经过内置规则计算后返回一个结果。你可以把它理解成一个加工车间:原材料进去,成品出来。MySQL 官方把函数分成字符串函数、数值函数、日期时间函数、流程控制函数、聚合函数等几大类,日常开发里几乎每条稍复杂一点的 SQL 都会用到其中一类。
举个例子,你要查用户表里每个人的姓名长度,不能靠肉眼数,这时可以用 CHAR_LENGTH(name);你要算订单表中每个月的销售额,需要把下单时间格式化成年月,这时可以用 DATE_FORMAT(order_time, '%Y-%m');你还要处理 NULL 值,避免页面上显示空白,这时离不开 IFNULL。这些操作全部依赖函数。
我见过很多刚入行的同事,SQL 能写基础的增删改查,但一到统计报表、数据处理就卡壳,核心原因不是不会写 SELECT,而是不熟悉函数能提供什么能力。函数掌握得越熟,你写 SQL 的速度越快,也能少绕很多弯路。面试的时候,函数相关的问题也几乎必考,尤其是 COUNT 系和 CASE WHEN,所以要重视这块基础。
1.2 准备一张表,后面案例都用它
为了不让你看得云里雾里,我提前建一张员工表,后续的函数案例基本都围绕它展开。这张表结构简单,但足够覆盖字符串、数值、日期和聚合统计等场景。
sql复制CREATE TABLE emp (
emp_id INT PRIMARY KEY,
emp_name VARCHAR(50),
department VARCHAR(50),
hire_date DATE,
salary DECIMAL(10, 2)
);
INSERT INTO emp (emp_id, emp_name, department, hire_date, salary) VALUES
(1, '张三', '技术部', '2021-06-15', 18000.00),
(2, '李四', '技术部', '2020-03-01', 22000.00),
(3, '王五', '运营部', '2022-11-20', 12000.00),
(4, '赵六', '运营部', '2019-07-08', 15000.00),
(5, '孙七', '产品部', '2023-01-10', 16000.00),
(6, '周八', NULL, '2022-05-05', 10000.00);
这张表里有几个特点值得留意:姓名是中文,处理长度时要区分字符数和字节数;部门有空值,用于测试聚合函数处理 NULL 的行为;入职日期跨度大,方便做日期差计算。你可以在本地 MySQL 里先执行上面的建表和插入语句,后面我给出的每段 SQL 你都亲手跑一遍,比干看效果好太多。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 字符串函数实操:拼接、截取、清洗全流程
2.1 字符串拼接:CONCAT 和 CONCAT_WS,别被 NULL 坑到
字符串函数里使用频率最高的应该就是拼接。MySQL 提供了 CONCAT 和 CONCAT_WS 两个函数,前者按顺序把所有参数拼成一个字符串,后者在拼接时自动插入分隔符。
sql复制SELECT CONCAT(emp_name, '在', IFNULL(department, '未知部门'), '工作') AS info FROM emp;
这条 SQL 会返回类似“张三在技术部工作”的文本。注意我在中间用了 IFNULL(department, '未知部门'),这是因为 CONCAT 有一个非常容易踩坑的特性:只要任何一个参数为 NULL,整个结果就是 NULL。员工的部门为空时,如果不处理,得到的结果直接是 NULL,而不是“张三在未知部门工作”。
CONCAT_WS 的全称是 Concatenate With Separator,第一个参数是分隔符,后面跟多个字段。它和 CONCAT 最大的区别是:CONCAT_WS 会自动跳过 NULL 值,不会因为某一个字段为空就让整个结果变 NULL。
sql复制SELECT CONCAT_WS('-', emp_id, emp_name, department) AS tag FROM emp;
比如周八的部门是 NULL,上面这段 SQL 依然会返回“6-周八”,分隔符和字段之间也不会出现多余的空隔符。所以当你要拼多个字段并希望忽略空值时,优先考虑 CONCAT_WS,没必要自己写一堆 IFNULL。
2.2 截取和长度:SUBSTRING、SUBSTR、LEFT、RIGHT、LENGTH、CHAR_LENGTH
截取字符串在数据清洗里非常常见。MySQL 里 SUBSTRING(str, pos) 或 SUBSTRING(str, pos, len) 都能截取子串,SUBSTR 是它的同义词,两者完全等价,你不用纠结选哪个。需要注意 MySQL 的字符位置是从 1 开始数的,不是像编程语言那样从 0 开始。
我经常用这个特性做姓名脱敏。比如页面上要显示“张**”,可以这么写:
sql复制SELECT CONCAT(SUBSTRING(emp_name, 1, 1), '**') AS masked
