OPENJSON必须配合WITH子句才能映射业务字段;不加WITH只返回key、value、type三列,无法直接用于业务查询。

OPENJSON必须配合WITH子句才能映射业务字段
不加WITH的OPENJSON只返回key、value、type三列,没法直接用作业务查询。你看到的“解析失败”,大概率是忘了写WITH,或者写了但路径/类型不匹配。
-
WITH中列名可以自定义(比如JSON里是"user_id",你映射成id INT '$.user_id'完全合法) - 但类型必须与JSON实际值兼容:JSON里
"age": "25"(字符串)配INT会返回NULL;"is_active": "true"配BIT也一样 - 路径必须以
$开头,'$.data.items[0].name'对,'data.items[0].name'直接静默返回NULL
嵌套数组和对象要用CROSS APPLY + OPENJSON分层展开
单层OPENJSON只能处理顶层或指定子路径,遇到"orders": [{"id":1,"items":[{"sku":"A"}]}]这种结构,不能靠一个WITH全搞定。
- 先用
OPENJSON(@json, '$.orders')展开订单数组 - 再对每行结果
CROSS APPLY OPENJSON(value, '$.items') WITH (sku NVARCHAR(20) '$.sku')展开子项 - 别试图在第一层
WITH里写sku NVARCHAR(20) '$.orders[0].items[0].sku'——这只会取到第一个订单的第一个商品,且无法关联多行
调试时务必加ERROR ON ERROR,否则路径错你也发现不了
JSON_VALUE和OPENJSON默认对路径错误、类型不匹配、空值都返回NULL,不是报错。你在开发阶段看到NULL,90%不是数据真为空,而是路径写错了。
- 临时调试加
ERROR ON ERROR:JSON_VALUE(@json, '$.user.profile.phone' ERROR ON ERROR),一错立刻中断并提示路径问题 -
OPENJSON本身不支持ERROR ON ERROR语法,但你可以先用ISJSON(@json)确认输入合法,再用JSON_VALUE抽几个关键字段验证路径 - 注意:数据库兼容级别必须≥130,否则
OPENJSON根本不可用,查sys.databases里的compatibility_level确认
别把JSON_QUERY当JSON_VALUE用,否则前端解析会炸
如果JSON里某个字段是对象或数组(比如"tags": ["a","b"]),用JSON_VALUE提取会返回NULL;必须用JSON_QUERY保留原始结构。
-
JSON_VALUE(@j, '$.tags')→NULL(因为tags不是标量) -
JSON_QUERY(@j, '$.tags')→["a","b"](原样字符串,无额外引号) - 若拼接进新JSON:
CONCAT('{ "list": ', JSON_QUERY(@j, '$.tags'), ' }')安全;误用JSON_VALUE会导致变成"list": "[\"a\",\"b\"]",前端JSON.parse()直接报错
复杂点在于嵌套层级越深,CROSS APPLY链越长,容易漏掉某一层的ISJSON校验或路径根节点偏移;最容易被忽略的是兼容级别和输入类型——OPENJSON只认NVARCHAR,哪怕源列是VARCHAR,也得先CAST。











