SQL 中的核心字符串函数
第 3.2 课 · 阅读时间:约 8 分钟 · 练习题 ↓
在本课中,你将学习可以直接在查询中清理和转换文本的 SQL 字符串函数。我们会介绍何时使用 UPPER、LOWER、TRIM、SUBSTRING、CONCAT 等函数,并通过实例进行练习。学完本课后,你将能够在实际任务中熟练处理文本字段。
在上一课中,你从整体上了解了 SQL 内置函数。现在我们专门来看字符串函数,因为文本字段经常需要额外处理:统一大小写、去除多余字符、拼接值以及提取片段。
这些操作在分析、报表和数据准备中非常常见。你对字符串函数越熟悉,在 SQL 之外需要手动做的后期处理就越少。
什么是字符串函数
字符串函数处理文本,并返回字符串、数字或子串的位置。在以下情况下它们很有用:
- 把文本统一成一致的格式;
- 清理含有杂质的值;
- 提取字符串的一部分(例如邮箱的域名);
- 为报表生成易读的输出。
基本语法
FUNCTION_NAME(string_expression, ...)
大多数情况下,参数是表的列、字符串字面量或其他函数的结果。
核心字符串函数
UPPER() 和 LOWER()
用于统一文本的大小写。
SELECT
customer_id,
UPPER(last_name) AS last_name_upper,
LOWER(first_name) AS first_name_lower
FROM customer
LIMIT 5;
结果:姓氏以大写显示,名字以小写显示。
CHAR_LENGTH() 和 LENGTH()
这两个函数都用于测量字符串长度,但方式不总是相同:
CHAR_LENGTH()通常返回字符数;- MySQL 中的
LENGTH()返回字节数。
SELECT
title,
CHAR_LENGTH(title) AS title_chars,
LENGTH(title) AS title_bytes
FROM film
LIMIT 5;
说明:对于多字节字符,字节数可能大于字符数。
SUBSTRING()、LEFT()、RIGHT()
这些函数用于提取字符串的一部分。
SELECT
email,
SUBSTRING(email, 1, 5) AS email_start,
LEFT(email, 3) AS first_3,
RIGHT(email, 10) AS last_10
FROM customer
LIMIT 5;
结果:提取出邮箱的不同片段,用于分析和格式检查。
CONCAT() 和 CONCAT_WS()
这些函数把多个值合并成一个字符串:
CONCAT()直接拼接各个参数;CONCAT_WS(separator, ...)会插入分隔符,在报表中通常更实用。
SELECT
customer_id,
CONCAT(first_name, ' ', last_name) AS full_name,
CONCAT_WS(' | ', first_name, last_name, email) AS customer_label
FROM customer
LIMIT 5;
说明:遇到 NULL 时的行为取决于 DBMS,请务必查阅你所用系统的文档。
TRIM() 和 REPLACE()
用于清理文本值。
SELECT
address,
TRIM(address) AS address_trimmed,
REPLACE(address, 'Street', 'St.') AS address_short
FROM address
LIMIT 5;
结果:去掉多余的空格,并替换重复出现的文本片段。
查找子串:POSITION() / INSTR() / CHARINDEX()
函数名取决于 DBMS,但思路相同:在字符串中查找子串的位置。
SELECT
email,
INSTR(email, '@') AS at_pos
FROM customer
LIMIT 5;
结果:返回 @ 的位置,这对校验邮箱很有用。
需要注意的地方
- 检查不同 DBMS 之间的差异:函数名和行为可能不同。
- 小心
NULL:它经常会改变字符串表达式的结果。 - 处理西里尔字母和表情符号等文本时,要有意识地选择长度函数(字符数还是字节数)。
- 避免在一条查询中嵌套过多函数;尽可能把逻辑拆成几步。
实践示例:为邮件营销准备客户数据
下面的查询准备了一份干净的客户列表:规范化姓名和邮箱,并提取域名。
SELECT
c.customer_id,
TRIM(CONCAT_WS(' ', c.first_name, c.last_name)) AS full_name,
LOWER(TRIM(c.email)) AS email_normalized,
SUBSTRING_INDEX(LOWER(TRIM(c.email)), '@', -1) AS email_domain
FROM customer AS c
WHERE c.email IS NOT NULL
ORDER BY c.customer_id
LIMIT 20;
结果:得到一组干净、一致的文本字段,可直接用于分析或导出。
本课要点:
- SQL 字符串函数可以直接在查询中清理、规范化和格式化文本。
UPPER、LOWER、TRIM、REPLACE、SUBSTRING、LEFT、RIGHT和CONCAT能完成大多数常见任务。- 计算字符串长度时,区分字符和字节很重要。
- 拼接字符串时,要考虑你所用 DBMS 对
NULL的处理方式。 - 字符串函数的实际价值在真实的数据准备工作中体现得最明显。
常见问题
如何在 SQL 中删除字符串中的空格?
TRIM(column) 删除开头和结尾的空格,LTRIM 和 RTRIM 只删除一侧的空格。要删除所有空格(包括字符串中间的空格),请使用 REPLACE(column, ' ', '')。在 MySQL 和 PostgreSQL 中,TRIM 还可以删除其他字符:TRIM(BOTH '.' FROM column)。
如何在 SQL 中拼接字符串?
CONCAT(first_name, ' ', last_name) 适用于 MySQL、PostgreSQL 和 SQL Server。标准运算符 || 适用于 PostgreSQL、SQLite 和 Oracle,但在 MySQL 中默认表示逻辑 OR。CONCAT_WS(' ', first_name, last_name) 会自动在各值之间插入分隔符。
如何在 SQL 中检查字符串是否包含某个子串?
筛选行时使用 LIKE:WHERE email LIKE '%@sakilacustomer.org'。要获取位置,在 MySQL 中用 INSTR(email, '@'),在标准 SQL 和 PostgreSQL 中用 POSITION('@' IN email),在 SQL Server 中用 CHARINDEX('@', email)。位置为 0 表示没有找到该子串。
面试问题
CHAR_LENGTH() 和 LENGTH() 有什么区别,为什么这很重要?
CHAR_LENGTH() 通常返回字符数,而 MySQL 中的 LENGTH() 返回字节数。对于西里尔字母和其他多字节字符,两者的结果可能不同。这在校验字段长度和执行业务规则时很重要。
如果某个字段可能为 NULL,如何安全地拼出全名?
通常更推荐 CONCAT_WS(),因为用分隔符拼接字符串时它很实用。另一种常见做法是用 COALESCE() 显式处理空值,以便在不同情况下得到可预期的结果。
在分析之前,你会用哪些字符串函数清理邮箱数据?
常见做法是 TRIM() + LOWER(),去掉多余空格并统一大小写。要校验结构,还可以用 INSTR() 或你所用 DBMS 中的等价函数检查是否包含 @。