必须用 NVARCHAR(MAX) 声明 JSON 参数并前置 ISJSON() 校验,否则 JSON_VALUE/OPENJSON 静默返回 NULL;中文键名需转义,数组用方括号,多字段提取须用 OPENJSON WITH,解析结果应暂存再提交以保障事务一致性。

必须用 NVARCHAR(MAX) 声明参数,且解析前不校验 ISJSON() 就等于埋雷——JSON_VALUE 和 OPENJSON 全部静默返回 NULL,不是报错,而是“假装成功”。
参数声明必须是 NVARCHAR(MAX),不能是 VARCHAR 或 NVARCHAR(4000)
SQL Server 没有原生 JSON 类型,所有 JSON 都靠字符串承载。用 VARCHAR 会导致中文键名(如 "收货地址")、emoji 或 Base64 字段乱码或截断;用 TEXT 或 XML 类型则直接不兼容 JSON 函数。
路径和内容内部按 Unicode 解析,NVARCHAR 是强制要求。长度不能写 NVARCHAR(4000)——哪怕你“确定”不会超长,实际运行中含图片 Base64 的 JSON 很容易踩坑。
- 正确:
@json_param NVARCHAR(MAX) - 错误:
@json_param VARCHAR(8000)、@json_param TEXT、@json_param NVARCHAR(4000)
ISJSON() 校验不是可选步骤,是执行前必做的安全闸
漏掉这一步,后续所有 JSON_VALUE、OPENJSON 调用都会静默返回 NULL,而不是抛异常。你看到的“字段为空”,很可能是 JSON 格式非法,而非业务数据缺失。
- 在存储过程开头立即校验:
IF ISJSON(@json_param) = 0 THROW 50000, 'Invalid JSON input', 1; - 不要只在开发环境校验——生产环境里前端传参拼错一个逗号、多一个逗号、少一个引号,都足以让整个解析链失效
- 注意:空字符串
''、NULL、纯空白都返回0,需提前判断是否允许空输入
取单个标量值用 JSON_VALUE,但路径写错或类型不匹配就返回 NULL
JSON_VALUE 只接受指向字符串、数字、布尔或 null 的路径;一旦路径指向对象(如 $.address)或数组(如 $.tags),结果就是 NULL,不是函数失效,而是语义不匹配。
- 中文键名必须转义:
'$.["收货地址"]',不能写'$.收货地址' - 数组元素用方括号:
'$[0].amount'提取第一个订单金额 - 返回值默认是
NVARCHAR(4000),字段可能超长时要显式转换:CAST(JSON_VALUE(@json, '$.desc') AS NVARCHAR(MAX)) - 别在
WHERE里裸用:WHERE JSON_VALUE(data, '$.status') = 'done'——没索引时每次全表解析 JSON,性能崩得快
多字段、嵌套结构或数组展开,必须用 OPENJSON + WITH
从同一段 JSON 提取 3 个以上字段,或字段跨不同层级(如 $.user.name 和 $.order.items[0].price),硬写一堆 JSON_VALUE 不仅难维护,CPU 开销也高。
-
OPENJSON必须配WITH才能映射成可用列;不带WITH只返回key/value/type三列,全是字符串,没法直接用于业务逻辑 - 路径必须以
$开头:'$.user.name'对,'user.name'静默失败 - 嵌套数组要用
CROSS APPLY分层展开:先OPENJSON(@json, '$.orders'),再对每行CROSS APPLY OPENJSON(value, '$.items') - 示例:
OPENJSON(@json) WITH (name NVARCHAR(50) '$.user.name', price DECIMAL(10,2) '$.order.items[0].price')
最容易被忽略的是:JSON 解析本身没有事务性,OPENJSON 出错不会回滚前面已插入的数据;如果业务逻辑涉及主子表写入,必须把 JSON 解析结果先存到临时表或表变量里,验证通过后再批量提交——否则部分成功、部分失败的状态极难追溯。


















