2人参与 • 2026-08-07 • Mysql
在日常的数据库开发中,字符串处理绝对是最频繁的操作之一——拼接用户姓名、截取手机号后四位、格式化输出、替换敏感信息……如果没有字符串函数,这些看似简单的需求都会变得无比复杂。
今天,我们就来系统性地梳理mysql中的字符串处理函数,每个都配上可直接运行的示例,让你看完就能用上。
concat() 用于将多个字符串连接成一个字符串。
-- 基础用法:拼接多个字符串
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 的升级版,第一个参数指定分隔符,后续参数是要拼接的内容。
-- 用 '-' 拼接日期
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(str, pos, len) 从指定位置开始截取指定长度的子串。
-- 从第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
select left('hello world', 5); -- 输出:hello
select right('hello world', 5); -- 输出:world
按分隔符截取字符串的某一部分,非常适合处理 csv 格式的数据。
-- 取第一个逗号之前的内容
select substring_index('apple,banana,orange', ',', 1);
-- 输出:apple
-- 取最后一个逗号之后的内容(负数表示从右往左数)
select substring_index('apple,banana,orange', ',', -1);
-- 输出:orange
replace(str, from_str, to_str) 将字符串中所有出现的 from_str 替换为 to_str。
-- 基础替换
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(str, pos, len, newstr) 从 pos 位置开始,将长度为 len 的子串替换为 newstr。
-- 从第3位开始,替换4个字符
select insert('quadratic', 3, 4, 'what');
-- 输出:quwhattic
两者功能相同,只是参数顺序不同。
-- 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;
select upper('hello'); -- 输出:hello
select lower('hello'); -- 输出:hello
upper() 和 ucase() 等价,lower() 和 lcase() 等价。
select trim(' hello '); -- 输出:hello(去除两端空格)
select ltrim(' hello'); -- 输出:hello(去除左侧空格)
select rtrim('hello '); -- 输出:hello(去除右侧空格)
trim() 只去除字符串头部和尾部的空格,中间的空格不会被删除。
-- 左填充:用 '0' 在左边填充到总长度5
select lpad('1', 5, '0');
-- 输出:00001
-- 右填充:用 '*' 在右边填充到总长度10
select rpad('name', 10, '*');
-- 输出:name******
-- 实战:学号统一补足6位
update student set sn = lpad(sn, 6, '0');
select length('mysql'); -- 输出:5(字节数)
select char_length('数据库'); -- 输出:3(字符数,一个汉字算1个字符)
在 utf-8 编码下,一个汉字占 3 个字节,一个英文字母占 1 个字节。
select reverse('hello');
-- 输出:olleh
select repeat('ha', 3);
-- 输出:hahaha
select ascii('a'); -- 输出:97
select ascii('ab'); -- 输出:97(只返回第一个字符)
这一组函数专门用来处理逗号分隔的字符串列表(csv格式),在标签系统、权限控制、多选字段和自定义排序中极其好用。
find_in_set(str, strlist) 返回子串在逗号分隔列表中的位置索引(从1开始),找不到则返回0。
-- 基础查找
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(n, str1, str2, ...) 返回第 n 个位置的字符串。非常适合做枚举值的美化映射。
-- 取第2个元素 select elt(2, 'spring', 'summer', 'autumn', 'winter'); -- 输出:summer -- 实战:将数字状态码转为中文描述(1-待支付, 2-已支付, 3-已取消) select order_id, elt(status, '待支付', '已支付', '已取消') as status_desc from orders;
field(str, str1, str2, ...) 返回 str 在后面列表中的首次出现位置(从1开始),找不到返回0。它与 find_in_set 功能互补,但参数形式不同(一个是逗号字符串,一个是枚举列表)。
-- 基础查找
select field('orange', 'apple', 'banana', 'orange', 'grape');
-- 输出:3
-- 🔥 最强实战:自定义排序(将状态按 待支付 → 已支付 → 已取消 的顺序排列)
select * from orders
order by field(status, 'pending', 'paid', 'cancelled');
-- 注意:不在列表中的 status 会排在最前面(因为返回0),可用此特性做兜底
make_set(bits, str1, str2, ...) 根据 bits 的二进制位,挑选对应位置的字符串并用逗号拼接返回。
-- 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, …) | 拼接后的逗号列表 | 权限标签组合 |
select concat(first_name, ' ', last_name, ' <', email, '>') as full_info from users; -- 输出:张三 <zhangsan@example.com>
select concat(left(email, 3), '***', substring(email, instr(email, '@'))) as masked_email from users; -- 输出:exa***@gmail.com
select username, length(username) as username_length from users order by username_length desc;
select concat('ord', date_format(now(), '%y%m%d'), lpad(order_seq, 4, '0'))
as order_no from orders;
-- 输出:ord202608060001
-- 查询同时包含 "科技" 和 "金融" 标签的文章(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 |
以上就是从入门到实战详解mysql中字符串处理函数完全指南的详细内容,更多关于mysql字符串处理的资料请关注代码网其它相关文章!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论