SQL Server JSON处理必须用NVARCHAR(MAX)声明参数,解析前必校验ISJSON(),单值用JSON_VALUE、多字段用OPENJSON WITH,路径须以$开头并正确转义中文键名,更新优先用JSON_MODIFY但避免动态路径拼接。

参数声明必须用 NVARCHAR(MAX),别碰 VARCHAR 或固定长度
SQL Server 没有原生 JSON 类型,所有 JSON 都是字符串,但必须是 Unicode 字符串。用 VARCHAR 会导致中文键名(如"收货地址")、emoji、Base64 字段乱码或截断;用 NVARCHAR(4000) 看似够用,实际含图片 Base64 的 JSON 很容易超长,静默截断后 ISJSON() 都可能返回 0。必须写成:@json_input NVARCHAR(MAX)。
解析前必调 ISJSON(),否则 JSON_VALUE 和 OPENJSON 全部静默返回 NULL
这是最常踩的坑:不校验就直接 JSON_VALUE(@json, '$.name'),结果字段为空——你根本不知道是数据没传、路径错、还是 JSON 本身非法。ISJSON() 返回 1 才代表可安全解析。建议在存储过程开头加判断:
IF ISJSON(@json_input) 1
BEGIN
THROW 50000, 'Invalid JSON input', 1;
END
不要用 WHERE JSON_VALUE(data, '$.status') = 'done' 这类裸用方式,没索引时等于全表逐行解析,性能崩得快。
提取单个标量用 JSON_VALUE,多字段或嵌套结构一律上 OPENJSON WITH
JSON_VALUE 只能取字符串、数字、布尔、null;一旦路径指向对象(如 $.address)或数组(如 $.tags),它就返回 NULL,不是报错,而是“语义不匹配”。中文键名必须转义:'$.["收货地址"]',不能写 '$.收货地址'。数组元素用方括号:'$[0].amount'。
如果要取 user.name、order.items[0].price、meta.updated_at 这类跨层级字段,硬写一堆 JSON_VALUE 不仅难维护,CPU 开销也高。正确做法是:
- 用
OPENJSON(@json_input) WITH (name NVARCHAR(50) '$.user.name', price DECIMAL(10,2) '$.order.items[0].price') - 嵌套数组必须分层
CROSS APPLY:先OPENJSON(@json, '$.orders'),再对每行CROSS APPLY OPENJSON(value, '$.items') - 路径必须以
$开头,'user.name'会静默失败
更新 JSON 内容优先用 JSON_MODIFY,但注意它不支持动态路径拼接
JSON_MODIFY 是唯一安全修改 JSON 字符串的函数,但它不接受变量拼接的路径,比如 '$.items[' + CAST(@i AS VARCHAR) + '].price' 会语法报错。新增键时父路径必须存在,否则整个操作失败(返回原值);删除键要用 lax $.key 模式,strict 下路径不存在直接报错。
真正麻烦的是大 JSON(>2MB)反复调用 JSON_MODIFY,性能差到不可接受。这种场景下,不如把原始 JSON 读出,在应用层处理完再整段回写——SQL Server 的 JSON 函数本质是字符串操作,不是真正的文档引擎。











