HOWTO · MySQL
在 MySQL 中拆分字符串
本教程演示如何在 MySQL 数据库中拆分字符串。
本页内容
在 MySQL 中,可用 SUBSTRING_INDEX() 提取分隔符一侧的文本。若要将每个部分分别作为一行返回,可将它与数字序列结合使用。如果值已经存储为 JSON 数组,则可使用 JSON 提取函数读取其中的元素;JSON 函数不能拆分任意带分隔符的文本。
使用 SUBSTRING_INDEX() 提取分隔符两侧的文本
SUBSTRING_INDEX(str, delim, count) 会在 count 为正数时,返回 str 中第 count 次出现 delim 之前的部分;当 count 为负数时,则返回对应位置右侧的部分。分隔符是一个字符串,也可以包含多个字符。如果字符串中没有指定次数的分隔符,函数会返回整个输入字符串。
例如,对于以逗号分隔的值 apple,banana,cherry,SUBSTRING_INDEX(value, ',', 1) 返回 apple,而 SUBSTRING_INDEX(value, ',', -1) 返回 cherry。嵌套调用可以提取中间字段:SUBSTRING_INDEX(SUBSTRING_INDEX(value, ',', 2), ',', -1) 返回 banana。若要将此表达式用于表中的数据,请把 value 替换为列名。
如果地址的两部分之间存有换行符,可使用 SUBSTRING_INDEX(address, '\n', 1) 获取第一个换行符之前的文本,并使用 SUBSTRING_INDEX(address, '\n', -1) 获取最后一个换行符之后的文本。在 MySQL 字符串字面量中,按照通常的转义规则,\n 表示换行符;如果 SQL 模式禁用了反斜杠转义,则需要以相应方式表示分隔符。
此处的 SQL 片段以行内代码展示,因为配置的文章运行环境不会执行 MySQL SQL。请将示例值或列名替换为自己的数据后,在 MySQL 数据库中运行。
将带分隔符的字符串拆分为多行
若要每行返回一个值,可将嵌套的 SUBSTRING_INDEX() 表达式应用于整数序列。下面的示例查询使用一个由 1 到 5 组成的派生序列:
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX('apple,banana,cherry', ',', numbers.n), ',', -1) AS fruit FROM (SELECT 1 AS n UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5) AS numbers WHERE numbers.n <= LENGTH('apple,banana,cherry') - LENGTH(REPLACE('apple,banana,cherry', ',', '')) + 1;
对于这个输入,表达式会选出第一个、第二个和第三个字段;WHERE 条件会统计逗号的数量,再加 1,以确定要返回多少个字段。结果表会包含 apple、banana 和 cherry,每行一个值。这是一个 MySQL 示例,配置的运行环境不会执行它。
这个序列有上限:该派生表最多只能生成五行。如果输入可能包含超过五个部分,请扩展序列,或与数字表连接。计数表达式假定输入非空,并将每个逗号都视为分隔符;使用此模式前,请确定应用程序如何处理空输入、连续分隔符,以及包含逗号的值。如果数据经常需要拆分,通常将每个值单独存为一行会更便于查询和维护。
读取 JSON 数组中的元素
如果某列已经包含有效的 JSON 数组,可使用 JSON 函数按从零开始的索引读取元素。这是数组访问方式,不能通用地拆分普通的带分隔符文本。对于类似 ["apple","banana","cherry"] 的数组,以下表达式展示了对应的元素路径:JSON_UNQUOTE(JSON_EXTRACT(json_column, '$[0]'))、JSON_UNQUOTE(JSON_EXTRACT(json_column, '$[1]')) 和 JSON_UNQUOTE(JSON_EXTRACT(json_column, '$[2]'))。它们依次返回 apple、banana 和 cherry,且不带 JSON 字符串的引号。请将 json_column 替换为你的 JSON 列。此示例假定数据是有效 JSON,且数组包含这些位置的元素;请根据服务器使用的 MySQL 版本确认相关函数是否可用。
选择合适的 MySQL 方法
- 需要提取已知分隔符位置之前或之后的一个子字符串时,使用
SUBSTRING_INDEX()。 - 查询需要将每个带分隔符的部分分别作为一行返回时,使用数字序列与嵌套的
SUBSTRING_INDEX()调用。确保序列长度足以覆盖最长的输入,并明确如何处理空值和重复分隔符。 - 数据已经是有效的 JSON 数组,且需要读取已知索引处的元素时,使用 JSON 提取。这不会将任意逗号分隔字符串转换为 JSON 数组。
如果经常按单个值筛选、连接或更新数据,可以考虑将这些值分别存为多行,而不是每次查询时再拆分字符串。