🎯 本月只剩几天支持 SQLTest.online,帮助我们让 SQL 练习对每个人都免费。 今天捐赠 →
SQL 代码已复制到剪贴板

SQL 中的核心字符串函数

第 3.2 课 · 阅读时间:约 8 分钟 · 练习题 ↓

在本课中,你将学习可以直接在查询中清理和转换文本的 SQL 字符串函数。我们会介绍何时使用 UPPER、LOWER、TRIM、SUBSTRING、CONCAT 等函数,并通过实例进行练习。学完本课后,你将能够在实际任务中熟练处理文本字段。

在上一课中,你从整体上了解了 SQL 内置函数。现在我们专门来看字符串函数,因为文本字段经常需要额外处理:统一大小写、去除多余字符、拼接值以及提取片段。

这些操作在分析、报表和数据准备中非常常见。你对字符串函数越熟悉,在 SQL 之外需要手动做的后期处理就越少。

作用于同一个邮箱的 SQL 字符串函数:CHAR_LENGTH、INSTR、LOWER、LEFT 和 SUBSTRING_INDEX,以及用 CONCAT_WS 拼出全名


什么是字符串函数

字符串函数处理文本,并返回字符串、数字或子串的位置。在以下情况下它们很有用:

  • 把文本统一成一致的格式;
  • 清理含有杂质的值;
  • 提取字符串的一部分(例如邮箱的域名);
  • 为报表生成易读的输出。

基本语法

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 中的等价函数检查是否包含 @。

尝试解决以下任务,以巩固您在本课中学到的内容。

  1. 客户全名
  2. 识别回文名字
  3. 从电子邮件中提取地址和域名
  4. 匹配客户的首字母
  5. 员工电话簿