json_table的核心价值是将json解析下推至数据库内核,需严格遵循路径表达式规则:根数组用'$[*]',对象内数组须用nested path;路径错误触发error 3143/3149,类型不匹配或越界返回null,on empty/on error必须显式配置。

直接在 SQL 里把 JSON 打平成行,不用拉到应用层解析 —— 这是 JSON_TABLE 的核心价值。它不是语法糖,而是把 JSON 解析逻辑下推到数据库内核的强制能力。
路径表达式写错就报 ERROR 3143 或 3149
路径必须合法且匹配实际数据结构,否则查询直接失败。
-
'$[*]'仅适用于根级数组;若源字段是对象(如{"items": [...]}),却写'$[*]',会报ERROR 3149 (HY000): The JSON path is not valid for the given JSON document - 漏引号、用双斜杠
//、写成'$.[*]'(中间多点)等,触发ERROR 3143 (42000): Invalid path expression - 路径指向字段存在但类型不匹配:比如
PATH '$.price'期望数字,但 JSON 里存的是字符串"price": "99.99",也会返回 NULL 或报错,取决于是否加了ON ERROR
嵌套数组必须用 NESTED PATH,不能硬套多层 COLUMNS
当 JSON 是“对象包数组”结构(如 {"order_id": 1, "items": [{"id": 101}, {"id": 102}]}),想同时取顶层字段和数组元素,必须分层定义。
- 错误写法:
JSON_TABLE(o.data, '$' COLUMNS (order_id INT PATH '$.order_id', item_id INT PATH '$.items[*].id'))——$.items[*].id在非根级路径中不被允许,结果为空或报错 - 正确写法:外层取对象字段,
NESTED PATH '$.items[*]'单独展开数组,其子COLUMNS中的PATH自动以当前数组元素为基准(即$指向{"id": 101}) -
NESTED PATH必须嵌套在最外层COLUMNS内,不可独立存在;每加一层,输出行数按该数组长度膨胀
列定义里 PATH 是相对路径,不是从根开始拼的
每个 COLUMNS 子句里的 PATH,都相对于它所属的路径上下文(主 path 或某层 NESTED PATH)。
- 主路径是
'$.items[*]',那么COLUMNS (name VARCHAR(50) PATH '$.name')中的$就指代每个items数组元素,不是整个原始 JSON - 如果主路径是
'$',又用了NESTED PATH '$.items[*]',那它内部的PATH '$.id'的$就是当前items元素,不是原始 JSON 的根 - 误写成
PATH '$.items[0].id'这类越界路径,即使数据有值,也可能返回 NULL —— 因为它试图从当前上下文再往下找items字段,而当前上下文已经是items的某个元素了
空值和异常要显式控制,别依赖默认行为
生产 JSON 数据质量差,字段缺失、类型错乱极常见。ON EMPTY 和 ON ERROR 不是可选项,是保命配置。
- 字段不存在时,默认返回 NULL;加
DEFAULT 'N/A'可避免后续聚合或 JOIN 出问题 - 类型转换失败(如字符串转 INT),默认可能报错中断查询;加
ON ERROR DEFAULT 0更鲁棒 - 需要序号列?用
item_index FOR ORDINALITY,它不依赖 PATH,也不受空值影响,稳定生成 1,2,3…
最容易被忽略的是路径上下文的嵌套层级和相对性 —— 看似只改了一个 $ 符号的位置,实际执行时指向的 JSON 片段可能完全不同。调试时建议先用 JSON_EXTRACT 验证路径是否真能取到值,再套进 JSON_TABLE。











