在数据库日常使用中,文本类数据的处理需求非常普遍,比如用户姓名格式统一、地址信息提取、日志内容清洗等场景,都离不开对字符串的操作。SQL语言自带了丰富的字符串函数,不需要额外编写复杂逻辑就能完成多数文本处理工作,掌握这些函数的用法和适用场景,能大幅提升文本数据处理的效率。

SQL常用字符串函数分类解析
SQL的字符串函数按功能可以分成几大类,不同数据库(如MySQL、PostgreSQL、SQL Server)的函数名称可能略有差异,但核心逻辑基本一致,下面以通用性较强的函数为例做详细说明。
1. 字符串拼接函数
拼接函数用于将多个字符串合并成一个,最常用的有两个:CONCAT()和CONCAT_WS()。
CONCAT()可以接收多个参数,按顺序拼接所有参数,如果其中有任意一个参数为NULL,整个拼接结果就会返回NULL。比如要拼接用户的姓和名得到完整姓名,写法如下:
-- 拼接姓和名,假设表user_info有first_name和last_name两个字段 SELECT CONCAT(first_name, last_name) AS full_name FROM user_info;
CONCAT_WS()的第一个参数是分隔符,后面是要拼接的字段或字符串,它会自动忽略NULL值,不会因为某个参数为NULL就返回整个结果为NULL,适合需要带分隔符拼接的场景,比如拼接地址的省、市、区:
-- 用横杠分隔拼接省市区,忽略NULL值
SELECT CONCAT_WS('-', province, city, district) AS address FROM user_address;2. 字符串截取函数
截取函数用于从原字符串中提取指定部分的内容,常用的有SUBSTRING()、LEFT()、RIGHT()。
SUBSTRING(str, start_pos, length)从字符串str的start_pos位置开始,截取长度为length的子串,位置索引一般从1开始。比如从身份证号中提取出生日期,身份证号第7到14位是出生日期:
-- 从18位身份证号中提取出生日期,假设id_card是身份证号字段 SELECT SUBSTRING(id_card, 7, 8) AS birth_date FROM user_info;
LEFT(str, length)从字符串左侧开始截取指定长度的子串,RIGHT(str, length)从右侧开始截取,适合固定位置在开头或结尾的提取场景。比如提取手机号的前三位判断运营商:
-- 提取手机号前三位 SELECT LEFT(phone, 3) AS phone_prefix FROM user_info;
3. 字符串替换与去空格函数
这类函数用于修改字符串的内容,常用的有REPLACE()、TRIM()、LTRIM()、RTRIM()。
REPLACE(str, old_str, new_str)把字符串str中的所有old_str替换成new_str,比如要把用户地址中的旧区名替换成新区名:
-- 把地址中的"老城区"替换成"新城区" SELECT REPLACE(address, '老城区', '新城区') AS new_address FROM user_address;
TRIM(str)去掉字符串左右两侧的空格,LTRIM(str)只去左侧空格,RTRIM(str)只去右侧空格,常用于用户输入内容的清洗,避免前后空格导致的数据匹配问题:
-- 清洗用户名,去掉前后空格 SELECT TRIM(user_name) AS clean_user_name FROM user_info;
4. 大小写转换与长度计算函数
UPPER(str)将字符串全部转为大写,LOWER(str)全部转为小写,常用于统一文本格式,比如邮箱地址统一转小写存储:
-- 邮箱转小写 SELECT LOWER(email) AS lower_email FROM user_info;
LENGTH(str)或者CHAR_LENGTH(str)用于计算字符串长度,前者按字节计算,后者按字符数计算,处理中文等多字节字符时用CHAR_LENGTH更准确,比如校验用户名长度是否在6到20位之间:
-- 查询用户名长度在6到20位的用户 SELECT user_name FROM user_info WHERE CHAR_LENGTH(user_name) BETWEEN 6 AND 20;
5. 字符串查找与判断函数
INSTR(str, substr)返回子串substr在字符串str中第一次出现的位置,如果没出现返回0,常用于判断字符串中是否包含某个关键词,比如找出地址中包含“科技园”的用户:
-- 查找地址包含"科技园"的用户 SELECT * FROM user_address WHERE INSTR(address, '科技园') > 0;
LIKE关键字配合通配符也是常用的查找方式,%代表任意长度字符,_代表单个字符,比如查找所有以“张”开头的姓名:
-- 查找姓张的用户 SELECT * FROM user_info WHERE user_name LIKE '张%';
文本数据处理的高效应用技巧
掌握基础函数后,结合具体场景合理组合使用,能解决很多复杂的文本处理需求,下面是几个常见场景的实践技巧。
1. 批量数据清洗
用户导入的数据往往存在格式不统一的问题,比如姓名可能有前后空格、大小写混杂,地址可能有重复的分隔符,用字符串函数组合可以快速批量处理。比如清洗用户姓名,统一去掉空格、首字母大写其余小写:
-- 清洗姓名:去空格,首字母大写,其余小写
SELECT
CONCAT(
UPPER(LEFT(TRIM(user_name), 1)),
LOWER(SUBSTRING(TRIM(user_name), 2))
) AS clean_user_name
FROM user_info;如果要处理地址中的多个连续分隔符,比如多个空格或者多个横杠,可以先把连续分隔符替换成单个,再处理:
-- 把地址中多个连续横杠替换成单个横杠 SELECT REPLACE(REPLACE(address, '--', '-'), '--', '-') AS clean_address FROM user_address;
2. 结构化数据提取
很多场景下文本字段存储的是非结构化或者半结构化数据,比如日志字段、备注字段,需要从中提取出有效信息。比如日志格式是“[时间] 操作人: 操作内容”,要提取操作人:
-- 从日志中提取操作人,假设log_content是日志内容字段
SELECT
SUBSTRING(
log_content,
INSTR(log_content, '操作人: ') + 4,
INSTR(log_content, ': 操作内容') - INSTR(log_content, '操作人: ') - 4
) AS operator
FROM system_log;如果是更复杂的半结构化数据,比如字段存储的是key=value格式的字符串,要提取特定key的值,可以结合字符串函数实现,比如提取“age=25;name=张三”中的age值:
-- 提取key=value字符串中age的值
SELECT
SUBSTRING(
info,
INSTR(info, 'age=') + 4,
INSTR(info, ';name=') - INSTR(info, 'age=') - 4
) AS age
FROM user_ext_info;3. 数据校验与格式统一
入库前对文本数据做格式校验,可以避免后续查询和统计出现问题。比如校验手机号是否为11位纯数字,邮箱格式是否包含@符号:
-- 校验手机号为11位纯数字,邮箱包含@
SELECT
phone,
CASE
WHEN CHAR_LENGTH(phone) = 11 AND phone REGEXP '^[0-9]+$' THEN '合法'
ELSE '不合法'
END AS phone_valid,
email,
CASE
WHEN INSTR(email, '@') > 0 THEN '合法'
ELSE '不合法'
END AS email_valid
FROM user_info;对于需要统一格式的内容,比如身份证号统一转大写(如果有字母的话),银行卡号统一去掉空格,都可以用对应的字符串函数批量处理,不需要单独写程序处理。
4. 分组统计与内容聚合
字符串函数也可以和分组统计结合,实现更灵活的数据统计需求。比如统计不同手机号前缀的用户数量:
-- 按手机号前三位分组统计用户数 SELECT LEFT(phone, 3) AS phone_prefix, COUNT(*) AS user_count FROM user_info GROUP BY LEFT(phone, 3) ORDER BY user_count DESC;
再比如统计每个用户的地址中出现的行政区数量,不过这种场景相对复杂,一般需要结合其他逻辑,但基础的字符串函数能完成很多前置的处理工作。
使用注意事项
不同数据库的字符串函数存在差异,比如MySQL的SUBSTRING和SQL Server的SUBSTRING参数一致,但PostgreSQL中也可以用SUBSTR,实际使用时需要先确认当前数据库的语法规则。另外,字符串函数嵌套过多会影响查询性能,如果处理的文本数据量非常大,建议先过滤数据再使用函数,或者考虑在应用层处理部分逻辑,避免数据库压力过大。还有,处理NULL值的时候要注意函数的特性,比如CONCAT遇NULL返回NULL,而CONCAT_WS会忽略NULL,根据实际需求选择对应的函数。