openjson必须配合with子句才能映射业务字段,否则仅返回key、value、type三列;路径缺“$.”前缀、类型不匹配、数组未用json_query或嵌套openjson、兼容级别低于130等均导致null或报错。

OPENJSON必须配WITH子句,否则只返回key/value/type三列
你写完OPENJSON(@json)却查不出业务字段?大概率是漏了WITH。不加WITH的OPENJSON永远只吐三列:key、value、type,没法直接SELECT name, age。业务字段映射全靠WITH里声明路径和类型。
常见错误:
-
WITH (id INT '$.id')写成WITH (id INT 'id')(缺$.前缀,静默返回NULL) -
WITH (tags NVARCHAR(100) '$.tags')但tags实际是数组,结果为NULL——该用JSON_QUERY或嵌套OPENJSON - JSON里
"age": "25"(字符串)配INT,返回NULL而非报错;调试时建议先用JSON_VALUE(@json, '$.age' ERROR ON ERROR)快速暴露路径或类型问题
嵌套数组要用CROSS APPLY分层展开,不能靠单层WITH硬写路径
面对{"orders": [{"id":1,"items":[{"sku":"A"},{"sku":"B"}]}]}这种结构,别在第一层WITH里写sku NVARCHAR(20) '$.orders[0].items[0].sku'——这只能取到第一个订单的第一个商品,且无法关联多行数据。
正确做法是两步走:
- 先用
OPENJSON(@json, '$.orders') WITH (order_id INT '$.id')展开订单行 - 对每行订单结果
CROSS APPLY OPENJSON(value, '$.items') WITH (sku NVARCHAR(20) '$.sku')展开商品 - 注意:第二层
OPENJSON的value来自第一层结果集的value列(不是原始@json变量)
处理可选字段或空数组时,路径错位会导致整行NULL,不是数据真为空
OPENJSON和JSON_VALUE对路径错误、键不存在、类型不匹配默认都返回NULL,不报错。你看到大量NULL,90%不是数据缺失,而是路径写错了。
排查建议:
- 用
ISJSON(@json)确认输入合法 - 挑1–2个关键字段,改用
JSON_VALUE(@json, '$.user.name' ERROR ON ERROR)测试路径(ERROR ON ERROR仅支持JSON_VALUE/JSON_QUERY) - 空数组
"someemptyproperty": []在OPENJSON(@json, '$.someemptyproperty')下返回零行,不是NULL——若需保留主记录,得用LEFT JOIN或OUTER APPLY
数据库兼容级别低于130时OPENJSON不可用,别跳过检查
OPENJSON从SQL Server 2016起引入,但要求数据库兼容级别≥130。如果执行时报“‘OPENJSON’ is not a recognized built-in function name”,不是语法错,是环境不达标。
检查并升级方式:
- 查当前级别:
SELECT compatibility_level FROM sys.databases WHERE name = DB_NAME() - 升级命令:
ALTER DATABASE CURRENT SET COMPATIBILITY_LEVEL = 150(推荐150,兼容性更好) - 注意:系统数据库(如
master)不能改,业务库才可操作
嵌套层级越深、数组越多,CROSS APPLY链越长,也越容易在某一层漏掉value引用或路径拼接错误——建议每展开一层就SELECT TOP 5 *验证中间结果,比最后查空再倒推快得多。











