MySQL 8.0.4+ 才支持 JSON_TABLE 实现字符串拆分,需先将原始字符串(如'a,b,c')用 REPLACE 和 CONCAT 转为合法 JSON 数组格式['a','b','c'],再通过 JSON_TABLE 解析,且 PATH 必须写 '$',注意转义、空值及性能问题。

MySQL 8.0+ 必须用 JSON_TABLE,低版本不行
MySQL 原生不支持类似 PostgreSQL 的 string_to_array() 或 SQL Server 的 STRING_SPLIT()。5.7 及更早版本只能靠递归 CTE(不支持)、自定义函数或应用层处理。只有 MySQL 8.0.4+ 引入了 JSON_TABLE,才真正能用纯 SQL 拆分字符串为多行——但前提是字符串得先转成合法 JSON 数组格式。
常见错误是直接对逗号分隔的原始字符串(如 'a,b,c')调用 JSON_TABLE,结果报错 Invalid JSON text。必须先用 REPLACE() 和字符串拼接转成 ["a","b","c"] 这样的形式。
正确构造 JSON 数组再传给 JSON_TABLE
核心是两步:把原始字符串包裹成 JSON 数组 + 用 JSON_TABLE 解析。注意引号、逗号、空格都要严格符合 JSON 规范。
- 原始字符串含双引号、反斜杠、换行时,必须先用
JSON_ESCAPE()(MySQL 8.0.22+)或手动替换,否则 JSON 解析失败 - 空值和空字符串要小心:
REPLACE('a,,c', ',', '","')会生成["a","","c"],这是合法的;但'a,,c'直接拆可能被误判为缺失项 - 分隔符是特殊字符(如竖线
|、制表符)时,REPLACE()要写对,比如REPLACE(col, '\t', '","')
示例:把 'apple,banana,cherry' 拆成三行:
SELECT fruit
FROM JSON_TABLE(
CONCAT('["', REPLACE('apple,banana,cherry', ',', '","'), '"]'),
'$[*]' COLUMNS (fruit VARCHAR(100) PATH '$')
) AS jt;
JSON_TABLE 的 COLUMNS 子句容易写错的点
COLUMNS 定义输出列时,PATH 必须写 '$' 表示取当前数组元素本身。写成 '$.name' 或留空会返回 NULL。
- 如果源字符串有嵌套结构(比如想拆的是 JSON 字段里的数组),不要重复套
JSON_TABLE,先用JSON_EXTRACT()提取外层数组再传入 - 类型声明要匹配实际数据:
fruit INT PATH '$'遇到字符串会转成 0,建议统一用VARCHAR再 CAST - 加
ORDINALITY可以获取原顺序:在COLUMNS里写idx FOR ORDINALITY,返回从 1 开始的序号
性能和可维护性提醒
每次调用都涉及字符串拼接 + JSON 解析,大数据量时比应用层拆分慢不少。单次处理几百行还行,上万行就得考虑缓存或预处理。
- 别在 WHERE 或 JOIN 条件里频繁用这个模式,MySQL 无法下推优化,容易全表扫描
- 如果分隔符固定且简单(如单字符),可封装成存储函数,但要注意函数内不能用动态 SQL,
JSON_TABLE必须写死在函数体中 - 线上环境务必测试空字符串、NULL 输入:
CONCAT('["', REPLACE(NULL, ',', '","'), '"]')会变成[""],不是你想要的空结果集
最麻烦的其实是错误定位——JSON_TABLE 报错信息很笼统,通常只说“Invalid JSON”,得回溯检查 CONCAT 后的中间字符串是否真能被 JSON_VALID() 通过。


















