openjson解析json数组需sql server 2016+,输入须为合法json字符串;默认仅解析顶层结构,嵌套需with子句指定路径;字段类型和路径必须显式声明,嵌套数组需二次openjson配合cross apply;参数应为nvarchar(max),性能优化需避免重复解析。

OPENJSON 解析 JSON 数组的基本前提
SQL Server 2016+ 才支持 OPENJSON,且必须确保输入是合法的 JSON 字符串。常见错误是传入非字符串类型(比如直接传 varchar 但内容含单引号未转义)、或 JSON 格式不标准(如尾部多逗号、键名没双引号)。OPENJSON 默认只解析顶层数组或对象,如果 JSON 是纯数组(如 [{"id":1,"name":"a"},{"id":2,"name":"b"}]),它能直接展开;但如果嵌套在对象里(如 {"data":[{"id":1}]}),就得配合 WITH 子句用路径定位。
使用前先验证:
SELECT ISJSON(@json_input) AS is_valid;返回 0 就别往下走了,否则
OPENJSON 返回空结果但不报错,容易误判。用 WITH 子句声明字段类型和路径
OPENJSON 不自动推断数据类型,必须用 WITH 显式定义列名、SQL 类型和 JSON 路径。路径写错(比如该用 $.data[0].name 却写成 $.name)会导致字段为 NULL。
典型写法:
SELECT * FROM OPENJSON(@json_array)<br>WITH (<br> id int '$.id',<br> name varchar(50) '$.name'<br>);注意:
-
'$.id'中的单引号不能漏,路径是字符串字面量 - 路径支持数组索引(
$[0].name),但一般不用——那是取单条,不是遍历数组 - 如果 JSON 字段名含点或空格,路径要用双引号括起来:
'$."user.name"' - NULL 值不会报错,但对应 SQL 列会是 NULL;若需默认值,得在
WITH里用DEFAULT或后续ISNULL
处理嵌套数组或动态结构
遇到类似 {"items":[{"val":1},{"val":2}], "meta":{"total":2}} 这种结构,不能靠一层 OPENJSON 拿到 items 里的数据。得先解析外层,再对 items 字段二次调用 OPENJSON:
SELECT j2.val<br>FROM OPENJSON(@json_obj) WITH (items nvarchar(max) '$.items') AS j1<br>CROSS APPLY OPENJSON(j1.items)<br>WITH (val int '$.val') AS j2;关键点:
-
items必须声明为nvarchar(max),否则无法被OPENJSON再次解析 -
CROSS APPLY是必须的,JOIN不行——因为OPENJSON是表值函数,需关联上一行的字段值 - 避免在循环里反复调用
OPENJSON,性能差;尽量用一次解析 + 多层APPLY拆解
存储过程中传参与性能注意点
在存储过程里接收 JSON,参数类型必须是 nvarchar(max),不能是 varchar(中文会乱码)、也不能是 json(SQL Server 没这个数据类型)。
性能上:OPENJSON 是解释执行,大数据量(如 >1000 条)时比原生表连接慢不少。如果频繁调用,考虑:
- 提前用
JSON_VALUE提取关键过滤字段,在WHERE中减少OPENJSON的输入规模 - 避免在
WHERE子句里直接写OPENJSON(...),会导致无法走索引(即使有计算列) - 临时表存中间结果比多次解析同一 JSON 更快,尤其需要多次引用时
实际用的时候,最常卡在路径写错、类型不匹配、或忘了把嵌套字段先提成 nvarchar(max)。JSON 看似灵活,但在 SQL 里每一步都得“钉死”结构,松一点就静默失败。











