在日常的数据库开发中,字符串处理绝对是最频繁的操作之一------拼接用户姓名、截取手机号后四位、格式化输出、替换敏感信息......如果没有字符串函数,这些看似简单的需求都会变得无比复杂。
今天,我们就来系统性地梳理MySQL中的字符串处理函数,每个都配上可直接运行的示例,让你看完就能用上。
一、字符串拼接:让散落的数据"粘"在一起
CONCAT ------ 基础拼接
CONCAT() 用于将多个字符串连接成一个字符串。
sql
-- 基础用法:拼接多个字符串
SELECT CONCAT('Hello', ' ', 'World');
-- 输出:Hello World
-- 拼接字段:把姓和名拼成全名
SELECT CONCAT(first_name, ' ', last_name) AS full_name FROM users;
⚠️ 踩坑提醒 :
CONCAT()的参数中只要有一个是NULL,整个结果就是NULL。比如CONCAT('My', NULL, 'QL')会返回NULL。
CONCAT_WS ------ 带分隔符的拼接
CONCAT_WS() 是 CONCAT 的升级版,第一个参数指定分隔符,后续参数是要拼接的内容。
sql
-- 用 '-' 拼接日期
SELECT CONCAT_WS('-', '2026', '08', '06');
-- 输出:2026-08-06
-- 拼接带格式的电话号码
SELECT CONCAT_WS('-', LEFT(phone, 3), SUBSTRING(phone, 4, 4), RIGHT(phone, 4))
AS formatted_phone FROM users;
-- 例如:13812345678 → 138-1234-5678
💡
CONCAT_WS()会自动忽略NULL值,比CONCAT()更安全。
二、字符串截取:精准"剪裁"你需要的部分
SUBSTRING ------ 按位置截取
SUBSTRING(str, pos, len) 从指定位置开始截取指定长度的子串。
sql
-- 从第1位开始截取5个字符
SELECT SUBSTRING('Hello World', 1, 5);
-- 输出:Hello
-- 提取邮箱域名(@之后的部分)
SELECT email, SUBSTRING(email, INSTR(email, '@') + 1) AS domain FROM users;
-- 输出:example@gmail.com → gmail.com
LEFT 和 RIGHT ------ 从两端截取
sql
SELECT LEFT('Hello World', 5); -- 输出:Hello
SELECT RIGHT('Hello World', 5); -- 输出:World
SUBSTRING_INDEX ------ 按分隔符截取
按分隔符截取字符串的某一部分,非常适合处理 CSV 格式的数据。
sql
-- 取第一个逗号之前的内容
SELECT SUBSTRING_INDEX('apple,banana,orange', ',', 1);
-- 输出:apple
-- 取最后一个逗号之后的内容(负数表示从右往左数)
SELECT SUBSTRING_INDEX('apple,banana,orange', ',', -1);
-- 输出:orange
三、字符串替换:修改内容的"橡皮擦"
REPLACE ------ 全局替换
REPLACE(str, from_str, to_str) 将字符串中所有 出现的 from_str 替换为 to_str。
sql
-- 基础替换
SELECT REPLACE('Hello World', 'World', 'MySQL');
-- 输出:Hello MySQL
-- 替换邮箱域名
SELECT REPLACE(email, '@old.com', '@new.com') AS new_email FROM users;
-- 多个匹配全部替换
SELECT REPLACE('apple banana apple', 'apple', 'orange');
-- 输出:orange banana orange
INSERT ------ 指定位置替换
INSERT(str, pos, len, newstr) 从 pos 位置开始,将长度为 len 的子串替换为 newstr。
sql
-- 从第3位开始,替换4个字符
SELECT INSERT('Quadratic', 3, 4, 'What');
-- 输出:QuWhattic
四、字符串查找:在大段文本中"定位"目标
INSTR 和 LOCATE ------ 查找子串位置
两者功能相同,只是参数顺序不同。
sql
-- INSTR(str, substr):先写字符串,再写子串
SELECT INSTR('Hello World', 'World');
-- 输出:7
-- LOCATE(substr, str):先写子串,再写字符串
SELECT LOCATE('World', 'Hello World');
-- 输出:7
-- 实战:查找名字中包含"李"的用户
SELECT * FROM users WHERE INSTR(name, '李') > 0;
五、大小写转换:统一文本格式
sql
SELECT UPPER('hello'); -- 输出:HELLO
SELECT LOWER('HELLO'); -- 输出:hello
💡
UPPER()和UCASE()等价,LOWER()和LCASE()等价。
六、去除空格:让数据更"干净"
sql
SELECT TRIM(' hello '); -- 输出:hello(去除两端空格)
SELECT LTRIM(' hello'); -- 输出:hello(去除左侧空格)
SELECT RTRIM('hello '); -- 输出:hello(去除右侧空格)
⚠️
TRIM()只去除字符串头部和尾部的空格,中间的空格不会被删除。
七、字符串填充:让数据"对齐"
LPAD 和 RPAD ------ 左右填充
sql
-- 左填充:用 '0' 在左边填充到总长度5
SELECT LPAD('1', 5, '0');
-- 输出:00001
-- 右填充:用 '*' 在右边填充到总长度10
SELECT RPAD('Name', 10, '*');
-- 输出:Name******
-- 实战:学号统一补足6位
UPDATE student SET sn = LPAD(sn, 6, '0');
八、字符串长度:区分"字符数"和"字节数"
sql
SELECT LENGTH('MySQL'); -- 输出:5(字节数)
SELECT CHAR_LENGTH('数据库'); -- 输出:3(字符数,一个汉字算1个字符)
⚠️ 在 UTF-8 编码下,一个汉字占 3 个字节 ,一个英文字母占 1 个字节。
九、其他实用函数
REVERSE ------ 反转字符串
sql
SELECT REVERSE('Hello');
-- 输出:olleH
REPEAT ------ 重复字符串
sql
SELECT REPEAT('Ha', 3);
-- 输出:HaHaHa
ASCII ------ 获取首字符的 ASCII 码
sql
SELECT ASCII('a'); -- 输出:97
SELECT ASCII('ab'); -- 输出:97(只返回第一个字符)
十、集合与列表处理:FIND_IN_SET 家族 🚀
这一组函数专门用来处理逗号分隔的字符串列表(CSV格式),在标签系统、权限控制、多选字段和自定义排序中极其好用。
FIND_IN_SET ------ 在逗号列表中查找元素位置
FIND_IN_SET(str, strlist) 返回子串在逗号分隔列表中的位置索引(从1开始),找不到则返回0。
sql
-- 基础查找
SELECT FIND_IN_SET('b', 'a,b,c,d'); -- 输出:2
SELECT FIND_IN_SET('e', 'a,b,c,d'); -- 输出:0
-- 实战:查询拥有"管理员"角色的用户(角色字段存的是 '编辑,管理员,审核')
SELECT * FROM users WHERE FIND_IN_SET('管理员', roles) > 0;
-- 实战:按给定的ID顺序查询(配合 ORDER BY)
SELECT * FROM products
WHERE FIND_IN_SET(id, '3,1,5,2') > 0
ORDER BY FIND_IN_SET(id, '3,1,5,2');
-- 结果将按 3 → 1 → 5 → 2 的顺序排列
⚠️ 特别注意 :
FIND_IN_SET的第二个参数必须是一个纯逗号分隔的字符串 ,不能包含空格 (如'a, b, c'会查找失败)。如果想忽略空格,需先结合REPLACE处理。
ELT ------ 按索引取元素
ELT(N, str1, str2, ...) 返回第 N 个位置的字符串。非常适合做枚举值的美化映射。
sql
-- 取第2个元素
SELECT ELT(2, 'Spring', 'Summer', 'Autumn', 'Winter');
-- 输出:Summer
-- 实战:将数字状态码转为中文描述(1-待支付, 2-已支付, 3-已取消)
SELECT order_id, ELT(status, '待支付', '已支付', '已取消') AS status_desc FROM orders;
FIELD ------ 按值查找位置(自定义排序神器)
FIELD(str, str1, str2, ...) 返回 str 在后面列表中的首次出现位置 (从1开始),找不到返回0。它与 FIND_IN_SET 功能互补,但参数形式不同(一个是逗号字符串,一个是枚举列表)。
sql
-- 基础查找
SELECT FIELD('orange', 'apple', 'banana', 'orange', 'grape');
-- 输出:3
-- 🔥 最强实战:自定义排序(将状态按 待支付 → 已支付 → 已取消 的顺序排列)
SELECT * FROM orders
ORDER BY FIELD(status, 'pending', 'paid', 'cancelled');
-- 注意:不在列表中的 status 会排在最前面(因为返回0),可用此特性做兜底
MAKE_SET ------ 按位掩码组合元素
MAKE_SET(bits, str1, str2, ...) 根据 bits 的二进制位,挑选对应位置的字符串并用逗号拼接返回。
sql
-- bits=3(二进制 011),取第1位和第2位
SELECT MAKE_SET(3, 'A', 'B', 'C', 'D');
-- 输出:A,B (因为 3 = 1+2,代表取第1个和第2个)
-- bits=5(二进制 101),取第1位和第3位
SELECT MAKE_SET(5, 'A', 'B', 'C', 'D');
-- 输出:A,C (因为 5 = 1+4)
-- 实战:通过权限位快速生成权限标签(1-读, 2-写, 4-执行)
SELECT user_id, MAKE_SET(permission_bit, '读权限', '写权限', '执行权限') AS permissions FROM user_roles;
-- 当 permission_bit = 6 时(110),输出:写权限,执行权限
本节函数速查对比:
| 函数 | 输入 | 输出 | 典型场景 |
|---|---|---|---|
FIND_IN_SET |
(值, '逗号列表') | 位置索引 | WHERE 条件判断 |
FIELD |
(值, 值1, 值2, ...) | 位置索引 | ORDER BY 自定义排序 |
ELT |
(索引, 值1, 值2, ...) | 对应值 | 枚举数字转文字 |
MAKE_SET |
(位掩码, 值1, 值2, ...) | 拼接后的逗号列表 | 权限标签组合 |
十一、综合实战案例
案例1:格式化用户信息
sql
SELECT CONCAT(first_name, ' ', last_name, ' <', email, '>') AS full_info
FROM users;
-- 输出:张三 <zhangsan@example.com>
案例2:脱敏处理(隐藏邮箱部分信息)
sql
SELECT CONCAT(LEFT(email, 3), '***', SUBSTRING(email, INSTR(email, '@')))
AS masked_email FROM users;
-- 输出:exa***@gmail.com
案例3:统计用户名长度并排序
sql
SELECT username, LENGTH(username) AS username_length
FROM users
ORDER BY username_length DESC;
案例4:生成固定格式的订单号
sql
SELECT CONCAT('ORD', DATE_FORMAT(NOW(), '%Y%m%d'), LPAD(order_seq, 4, '0'))
AS order_no FROM orders;
-- 输出:ORD202608060001
案例5:标签检索与自定义排序(新增)
sql
-- 查询同时包含 "科技" 和 "金融" 标签的文章(tags存为 '科技,金融,AI')
SELECT * FROM articles
WHERE FIND_IN_SET('科技', tags) > 0
AND FIND_IN_SET('金融', tags) > 0;
-- 将文章按指定的优先级排序(置顶推荐)
SELECT * FROM articles
ORDER BY FIELD(id, 1003, 1007, 1001, 1005) DESC, created_at DESC;
总结
MySQL 的字符串处理函数种类丰富、功能强大。掌握好这些函数,能让你的 SQL 语句更加简洁高效。建议收藏本文,在实际开发中遇到字符串处理需求时,随时查阅对照。
快速索引:
| 功能分类 | 核心函数 |
|---|---|
| 拼接 | CONCAT, CONCAT_WS |
| 截取 | SUBSTRING, LEFT, RIGHT, SUBSTRING_INDEX |
| 替换 | REPLACE, INSERT |
| 查找 | INSTR, LOCATE |
| 集合/列表处理 | FIND_IN_SET, FIELD, ELT, MAKE_SET |
| 大小写 | UPPER, LOWER |
| 去空格 | TRIM, LTRIM, RTRIM |
| 填充 | LPAD, RPAD |
| 长度 | LENGTH, CHAR_LENGTH |
| 其他 | REVERSE, REPEAT, ASCII |
希望这篇指南对你有帮助!如果你有更多好用的字符串函数技巧,欢迎在评论区分享交流 🚀
发布日期:2026-08-06