MySQL字符串截取:获取特定字符后的数据方法

11 次阅读

MySQL处理字符串时,经常会遇到“截取某个特定字符之后内容”的需求。例如,字段中保存了 user_10001、order_20261001、https://example.com/path 这类数据,需要快速提取下划线、斜杠、冒号等字符后面的部分。MySQL提供了多种字符串函数,可以根据分隔符的位置灵活完成这类操作。

一、使用SUBSTRING_INDEX获取特定字符后的数据

如果需求是按照某个字符进行分割,SUBSTRING_INDEX()通常是最直接的方法。

基本语法如下:

SQL
SUBSTRING_INDEX(str, delimiter, count)

其中:

  • str:需要处理的字符串;

  • delimiter:分隔字符或字符串;

  • count:指定从左侧或右侧开始查找的次数。

例如,表中有如下数据:

user_10001
user_10002
user_10003

想获取下划线 _ 后面的内容,可以使用:

SQL
SELECT SUBSTRING_INDEX('user_10001', '_', -1);

结果为:

10001

这里的 -1 表示从右侧开始查找最后一个 _,然后返回该分隔符右侧的内容。

如果字段中只有一个 _,这种写法非常简洁:

SQL
SELECT SUBSTRING_INDEX(username, '_', -1)
FROM user_info;

即可批量获取下划线之后的数据。

二、字符串包含多个相同字符时如何截取

实际数据可能并不只有一个分隔符。例如:

2026_10_01_order

如果执行:

SQL
SELECT SUBSTRING_INDEX('2026_10_01_order', '_', -1);

得到:

order

因为 -1 始终表示最后一个分隔符之后的内容。

如果希望获取第一个 _ 后面的全部内容,可以写成:

SQL
SELECT SUBSTRING_INDEX('2026_10_01_order', '_', -2);

结果:

10_01_order

也就是说,SUBSTRING_INDEX()不仅能够获取最后一个字符之后的数据,还可以控制从右侧截取多少个分隔部分。

三、使用SUBSTRING配合LOCATE截取

当需求更加明确,例如“找到第一个指定字符,然后获取它后面的全部内容”,可以将 SUBSTRING() 与 LOCATE() 结合使用。

假设字符串为:

product-apple-iphone

要求获取第一个 - 后面的数据:

SQL
SELECT SUBSTRING(
    'product-apple-iphone',
    LOCATE('-', 'product-apple-iphone') + 1
);

返回:

apple-iphone

LOCATE()负责查找字符的位置:

SQL
LOCATE('-', 'product-apple-iphone')

返回第一个 - 所在的位置。

然后通过:

SQL
+ 1

让 SUBSTRING()从分隔符的下一个字符开始截取。

这种方式适合需要明确控制“从第几个字符开始截取”的场景。

四、使用INSTR查找指定字符的位置

INSTR()与 LOCATE()的作用比较接近,同样可以用于查找字符第一次出现的位置。

例如:

SQL
SELECT INSTR('name:zhangsan', ':');

返回冒号的位置。

结合 SUBSTRING():

SQL
SELECT SUBSTRING(
    'name:zhangsan',
    INSTR('name:zhangsan', ':') + 1
);

结果:

zhangsan

如果是在查询表中的字段,可以写成:

SQL
SELECT SUBSTRING(
    user_info,
    INSTR(user_info, ':') + 1
)
FROM user_table;

这种写法的可读性较好,尤其适合需要表达“找到指定字符位置,再从其后开始截取”的场景。

五、使用SUBSTRING_INDEX获取域名、路径等数据

字符串截取并不局限于简单的下划线和冒号,在处理URL、文件路径、业务编码时也非常常见。

例如字段内容:

https://www.example.com/article/mysql

如果希望获取最后一个 / 后面的内容:

SQL
SELECT SUBSTRING_INDEX(
    'https://www.example.com/article/mysql',
    '/',
    -1
);

返回:

mysql

如果数据是:

/home/mysql/data/test.sql

同样可以:

SQL
SELECT SUBSTRING_INDEX(
    '/home/mysql/data/test.sql',
    '/',
    -1
);

得到:

test.sql

因此,对于“获取最后一个指定字符后的数据”这一类问题,SUBSTRING_INDEX(str, delimiter, -1)通常是最简洁的方案。

六、处理字段中不存在指定字符的情况

实际数据库中的数据并不一定都符合预期格式。例如:

user_10001
user_10002
admin
guest_10003

执行:

SQL
SELECT SUBSTRING_INDEX(username, '_', -1)
FROM user_info;

对于没有 _ 的 admin,返回的结果仍然是:

admin

这意味着 SUBSTRING_INDEX()不会因为找不到分隔符而直接报错,而是按照函数规则返回原字符串。

如果业务上要求只有存在指定字符时才截取,可以结合 LOCATE() 或 INSTR()进行判断:

SQL
SELECT
    CASE
        WHEN LOCATE('_', username) > 0
        THEN SUBSTRING_INDEX(username, '_', -1)
        ELSE NULL
    END AS user_id
FROM user_info;

这样可以将不符合格式的数据转换为 NULL,方便后续数据处理。

七、获取第一个特定字符后的数据

需要特别注意,“第一个字符后”和“最后一个字符后”是两种不同需求。

例如:

abc-def-ghi

获取第一个 - 后面的全部内容:

def-ghi

可以使用:

SQL
SELECT SUBSTRING_INDEX('abc-def-ghi', '-', -2);

这里容易产生误解,因为 SUBSTRING_INDEX()的负数参数是从右侧计算的。

更直观的方式是使用 LOCATE():

SQL
SELECT SUBSTRING(
    'abc-def-ghi',
    LOCATE('-', 'abc-def-ghi') + 1
);

结果:

def-ghi

如果只是需要最后一个 - 后面的内容,则直接使用:

SQL
SELECT SUBSTRING_INDEX('abc-def-ghi', '-', -1);

结果:

ghi

因此,选择函数之前首先要确定需求到底是“第一个分隔符之后”还是“最后一个分隔符之后”。

八、截取特定字符之后的一部分数据

有时并不是要一直截取到字符串末尾,而是只需要分隔符后面的固定长度内容。

例如:

order-20261001-10001

希望从第一个 - 后开始截取10个字符,可以使用:

SQL
SELECT SUBSTRING(
    'order-20261001-10001',
    LOCATE('-', 'order-20261001-10001') + 1,
    10
);

SUBSTRING()的完整形式为:

SQL
SUBSTRING(str, pos, len)

其中 len 可以控制最终返回的字符数量。

如果不指定长度:

SQL
SUBSTRING(str, pos)

则会一直截取到字符串末尾。

九、MySQL字符串截取的常见函数对比

针对不同的业务需求,可以选择不同函数。

函数主要用途典型场景
SUBSTRING_INDEX()按分隔符截取获取最后一个字符后的内容
SUBSTRING()按位置截取从指定位置开始获取字符串
LOCATE()查找字符位置获取第一个匹配字符的位置
INSTR()查找字符位置判断字符是否存在并定位
LEFT()从左侧截取获取字符串前N个字符
RIGHT()从右侧截取获取字符串后N个字符

如果只是处理类似:

abc_123456

获取 _ 后面的:

123456

优先考虑:

SQL
SUBSTRING_INDEX(column_name, '_', -1)

如果需要更加复杂的位置控制,再考虑 SUBSTRING()、LOCATE()等函数。

十、结合UPDATE批量处理字段

字符串截取不仅可以用于查询,也可以用于数据清洗。

例如原字段:

user_10001
user_10002
user_10003

如果要把截取后的编号保存到另一个字段,可以使用:

SQL
UPDATE user_info
SET user_id = SUBSTRING_INDEX(username, '_', -1);

执行前建议先使用 SELECT 验证:

SQL
SELECT
    username,
    SUBSTRING_INDEX(username, '_', -1) AS new_user_id
FROM user_info;

确认结果符合预期后,再执行 UPDATE。

对于生产环境中的数据修改,还应根据实际情况使用事务、备份或条件限制,避免误更新整张表。

十一、中文字符串截取需要注意什么

MySQL字符串函数对中文数据同样可以使用,但字符集和长度语义需要注意。

例如:

SQL
SELECT SUBSTRING('姓名:张三', 4);

在常见UTF-8字符集环境下,可以按照字符位置进行处理。

不过,如果数据库字段使用的字符集配置不合理,可能出现乱码或者字符存储异常。因此处理中文、表情符号以及多字节字符时,应检查数据库、表和字段的字符集配置。

可以通过以下语句查看连接相关字符集:

SQL
SHOW VARIABLES LIKE 'character_set%';

如果涉及中文业务数据,通常应确保相关字段采用合适的Unicode字符集,例如 utf8mb4。

十二、使用正则表达式处理复杂截取需求

当分隔规则比较复杂时,单纯依靠 SUBSTRING_INDEX()可能不够。

例如字符串:

user:10001@qq.com

如果需要根据多个可能的符号进行处理,可以考虑MySQL提供的正则相关能力。

在支持相应功能的MySQL版本中,可以结合 REGEXP_SUBSTR() 等函数处理更加复杂的文本提取。

例如,针对固定格式的数据,可以通过正则表达式提取符合规则的内容。不过,正则表达式的可读性和计算开销通常高于简单的字符串函数,因此对于明确的单字符分隔需求,没有必要为了“灵活”而使用正则。

十三、实际开发中的选择建议

如果需求非常明确,可以按照下面的思路选择:

获取最后一个指定字符之后的数据:

SQL
SELECT SUBSTRING_INDEX(column_name, '_', -1);

获取第一个指定字符之后的全部数据:

SQL
SELECT SUBSTRING(
    column_name,
    LOCATE('_', column_name) + 1
);

获取指定字符后固定长度的数据:

SQL
SELECT SUBSTRING(
    column_name,
    LOCATE('_', column_name) + 1,
    10
);

先判断字符是否存在:

SQL
SELECT
    CASE
        WHEN LOCATE('_', column_name) > 0
        THEN SUBSTRING_INDEX(column_name, '_', -1)
        ELSE NULL
    END
FROM table_name;

对于普通的业务字段拆分,SUBSTRING_INDEX()往往已经可以满足大多数需求;当涉及第一个分隔符、指定位置和固定长度时,SUBSTRING()配合LOCATE()会更加灵活。

需要特别注意的是,字符串截取本身虽然简单,但如果直接在大表查询条件、排序或关联条件中对字段使用函数,可能影响索引使用。例如:

SQL
WHERE SUBSTRING_INDEX(username, '_', -1) = '10001'

在数据量较大的情况下,可能无法充分利用原字段索引。若这种查询属于高频核心业务,可以考虑增加冗余字段、生成列或针对实际查询模式重新设计索引。

掌握 SUBSTRING_INDEX()、SUBSTRING()、LOCATE() 和 INSTR()之后,MySQL中绝大多数“获取特定字符前后内容”的字符串处理需求都可以灵活解决。实际使用时,关键不是记住某一个固定写法,而是先明确分隔符出现的位置、需要截取的范围,以及字段中是否可能存在异常数据,再选择最合适的函数组合。