JSON_TABLE必须置于FROM或JOIN子句中,是表函数而非标量函数;路径须含[*]以展开JSON数组;对NULL、非法JSON或非数组值静默跳过;字符串需先转为合法JSON数组格式。

JSON_TABLE必须放在FROM子句里,不能写在SELECT中
直接在SELECT里调用JSON_TABLE会报错:ERROR 1064 (42000): You have an error in your SQL syntax。它不是标量函数,而是表函数(table function),只能作为数据源出现在FROM或JOIN子句中。
常见错误写法:SELECT JSON_TABLE(...) AS jt —— 这是语法错误,MySQL根本不允许。
- 正确姿势是:
SELECT ... FROM table, JSON_TABLE(...)或SELECT ... FROM table JOIN JSON_TABLE(...) ON TRUE - MySQL 8.0.14+ 支持隐式
LATERAL,所以逗号连接和JOIN效果一致;但显式写LATERAL JOIN更清晰(如LATERAL JSON_TABLE(...)) - 若源表有100行,而某行的JSON字段为空数组或
NULL,该行在结果中将完全消失(不是返回NULL列,而是整行被过滤)
路径表达式必须带[*],否则不展开数组
JSON_TABLE只对**JSON数组**做“炸开”操作,且路径必须明确指向数组元素。写成'$.tags'不会报错,但返回空结果集——因为没匹配到任何数组项。
必须用'$.tags[*]'、'$[*]'或'$.items[*]'这类带[*]的路径。其中$代表当前数组元素,不是整个文档根。
- 若JSON是
{"roles": ["admin", "user"]},路径写'$.roles[*]',COLUMNS里用role VARCHAR(20) PATH '$'取每个字符串值 - 若JSON是
[{"id":1,"name":"a"},{"id":2,"name":"b"}],路径写'$[*]',COLUMNS里用id INT PATH '$.id'和name VARCHAR(50) PATH '$.name' - 路径中多一个点、少一个星号、括号用错(比如
[*]写成[0]),都会导致无输出行
处理NULL、非法JSON或非数组值时静默失败
JSON_TABLE对无效输入不抛异常,而是直接跳过该行——这是最容易被忽略的坑。比如字段值是NULL、空字符串''、字符串"not json",或$.items存在但值是"abc"(不是数组),整行都不会出现在结果里。
调试时发现行数变少,大概率是这个原因。别靠猜,先加校验:
- 用
JSON_VALID(col)确保字段是合法JSON - 用
JSON_TYPE(JSON_EXTRACT(col, '$.items')) = 'ARRAY'确认目标路径确实是数组类型 - 用
JSON_LENGTH(JSON_EXTRACT(col, '$.items')) > 0排除空数组 - 或者兜底:用
COALESCE(JSON_EXTRACT(col, '$.items'), JSON_ARRAY())把NULL转为空数组,避免丢行
字符串分割场景:必须先转成合法JSON数组
想拆分逗号分隔字符串'a,b,c'?JSON_TABLE不接受原始字符串,必须先构造合法JSON数组格式:'["a","b","c"]'。
关键步骤是两层包装:CONCAT('["', REPLACE(str, ',', '","'), '"]')。注意引号转义问题——如果原始字符串含双引号,得提前REPLACE(str, '"', '\"')。
- 错误示例:
JSON_TABLE('a,b,c', '$[*] COLUMNS (v TEXT PATH "$")')→ 报错Invalid JSON text - 正确写法:
JSON_TABLE(CONCAT('["', REPLACE('a,b,c', ',', '","'), '"]'), '$[*] COLUMNS (v TEXT PATH "$")') - 若字段名是
tag_list,完整查询类似:SELECT jt.v FROM t, JSON_TABLE(CONCAT('["', REPLACE(t.tag_list, ',', '","'), '"]'), '$[*] COLUMNS (v TEXT PATH "$")') AS jt
SELECT单独验证JSON_TABLE子查询的输出行数,别只看主查询逻辑。


















