JSON_TABLE是SQL标准中定义的一个强大函数,专门用于将JSON格式的数据转换为关系型表格形式。这个功能在MySQL 8.0+、Oracle 12c+等主流数据库中都得到了实现。它解决了传统SQL难以处理半结构化数据的痛点,让我们可以直接在数据库层面对JSON文档进行行列转换。
我最早接触这个函数是在处理电商平台的商品属性表时。当时商品特征都以JSON格式存储在单个字段中,需要提取特定属性进行分析报表。传统做法要么用应用代码处理,要么写复杂的字符串函数组合,而JSON_TABLE让这一切变得异常简单。
JSON_TABLE的基本语法包含四个关键部分:
sql复制JSON_TABLE(
json_doc,
path_expression COLUMNS (
column_definition [, column_definition]...
)
) [AS] alias
其中:
json_doc:可以是JSON字符串字面量,或者包含JSON数据的列path_expression:JSONPath表达式,定位要提取的数据节点column_definition:定义输出列的各种属性alias:必须提供的表别名每个列定义支持多种格式,最常用的有:
sql复制name type PATH 'json_path' [ON EMPTY] [ON ERROR]
name type EXISTS PATH 'json_path'
name FOR ORDINALITY
实际项目中,我经常组合使用这些格式。比如提取用户地址信息:
sql复制COLUMNS(
user_id FOR ORDINALITY,
country VARCHAR(20) PATH '$.address.country',
city VARCHAR(20) PATH '$.address.city',
has_phone BOOLEAN EXISTS PATH '$.phone'
)
假设商品表products中有个json_attrs字段存储规格参数:
json复制{
"dimensions": {
"width": 30,
"height": 45,
"depth": 15
},
"weight": 2.5,
"colors": ["red", "blue"]
}
提取关键参数的SQL:
sql复制SELECT p.product_name, jt.*
FROM products p,
JSON_TABLE(p.json_attrs, '$' COLUMNS(
width INT PATH '$.dimensions.width',
height INT PATH '$.dimensions.height',
weight DECIMAL(5,2) PATH '$.weight',
first_color VARCHAR(20) PATH '$.colors[0]'
)) AS jt
对于包含数组的数据,需要使用NESTED PATH:
json复制{
"order_id": "1001",
"items": [
{"product": "A", "qty": 2},
{"product": "B", "qty": 1}
]
}
解析SQL:
sql复制SELECT jt.*
FROM orders,
JSON_TABLE(order_json, '$' COLUMNS(
order_id VARCHAR(20) PATH '$.order_id',
NESTED PATH '$.items[*]' COLUMNS (
product VARCHAR(20) PATH '$.product',
quantity INT PATH '$.qty'
)
)) AS jt
虽然JSON_TABLE本身不能直接利用索引,但可以通过以下方式优化:
当处理MB级JSON文档时:
sql复制COLUMNS(
email VARCHAR(100) PATH '$.contact.email'
DEFAULT 'unknown' ON EMPTY
DEFAULT 'invalid' ON ERROR
)
sql复制COLUMNS(
-- 显式处理可能的字符串转数字
price DECIMAL(10,2) PATH '$.price'
ERROR ON ERROR
)
对于复杂嵌套结构,建议分步处理:
当JSON_TABLE不可用时,可以考虑:
但在大多数SQL操作场景中,JSON_TABLE提供了最佳的性能和便利性平衡。