json_modify不能直接使用变量路径,必须为字面量;动态场景需用case分支或经校验的动态sql;更新数组须确保路径存在,null值删除键而非设null,且不支持原地修改。

JSON_MODIFY 不能直接拼接路径字符串更新动态键名
SQL Server 的 JSON_MODIFY 不支持把 JSON 路径写成变量再直接传入——比如 JSON_MODIFY(@json, @path, @value) 会报错“参数 2 必须是字符串常量”。这是最常卡住人的地方。路径必须是字面量(literal),哪怕你用 CONCAT 拼出来也不行,SQL Server 在编译期就要求它可静态解析。
实际场景中,比如你要根据用户输入的字段名(如 'address.city')更新嵌套 JSON,就得绕开这个限制:
- 用
CASE或IIF显式列出常见路径分支,例如:JSON_MODIFY(@json, '$.address.city', @newCity)
和JSON_MODIFY(@json, '$.user.name', @newName)
分开处理 - 若路径完全不可预知(如配置表驱动),只能改用动态 SQL:
DECLARE @sql NVARCHAR(MAX) = N'SELECT JSON_MODIFY(@j, ''' + @path + ''', @v)'; EXEC sp_executesql @sql, N'@j NVARCHAR(MAX), @v NVARCHAR(MAX)', @j = @json, @v = @value;
注意:必须严格校验@path,防止注入(建议白名单过滤或正则匹配^[a-zA-Z0-9._$[\]]+$)
更新数组元素时路径语法容易出错
想改 JSON 数组里第 2 个对象的 price 字段?路径不是 '$.items[1].price' 就万事大吉——如果数组本身不存在,JSON_MODIFY 默认不会创建父结构。结果是返回原 JSON,悄无声息失败。
安全做法是分两步:
Miller (mlr) 是一个命令行工具,用于查询、整形和重新格式化名称索引数据,如 CSV、TSV、JSON 和 JSON Lines。它将 awk、sed、cut、join 和 sort 的功能整合到一个专为结构化数据处理而构建的单一工具中。
- 先确保路径存在:用
ISJSON()+JSON_VALUE检查$.items是否为有效数组 - 再用
JSON_MODIFY更新,且路径要完整。例如:JSON_MODIFY(JSON_MODIFY(@json, 'append $.items', JSON_OBJECT('id': 123)), '$.items[2].price', 99.9)这里append是关键,否则$.items[2]会因越界被忽略 - 注意索引从 0 开始,但
append后新元素索引是当前长度,不是硬写[2]—— 动态计算需配合JSON_QUERY提取数组再LEN/CHARINDEX数逗号,实际中往往不如用应用层处理
NULL 值和缺失字段的行为差异
传 NULL 给 JSON_MODIFY 第三个参数,效果取决于操作类型:
-
JSON_MODIFY(@json, '$.field', NULL)→ 删除field字段(不是设为null) -
JSON_MODIFY(@json, 'lax $.field', NULL)→ 如果field不存在,什么也不做;存在则删除 -
JSON_MODIFY(@json, 'strict $.field', NULL)→ 如果field不存在,抛错JSON path is not found - 想把字段值设为 JSON 的
null(即生成"field": null),必须显式传字符串'null':JSON_MODIFY(@json, '$.field', 'null')
(注意是字符串,不是 SQL 的NULL)
性能和兼容性边界要注意
JSON_MODIFY 在 SQL Server 2016+ 可用,但每次调用都会复制整个 JSON 字符串。如果 JSON 很大(>1MB)且频繁更新,CPU 和内存压力明显上升。
几个现实约束:
- 不支持原地修改:无论改一个字符还是整个对象,都重建整个 JSON 值
- 路径深度无硬限制,但超过 128 层可能触发解析错误,且性能急剧下降
- 无法原子更新多个字段:要改
a和b,必须嵌套调用两次JSON_MODIFY,中间结果不可见,且第二次调用基于第一次输出 —— 如果第一次出错,整个链路中断 - 对 Unicode 支持正常,但路径中含特殊字符(如空格、点号在键名里)必须用双引号括起来:
JSON_MODIFY(@json, '$."user name"."first.last"', 'John')
真正复杂的 JSON 操作,比如深层合并、条件更新、批量 patch,SQL 层很快会力不从心——这时候该交还给应用代码,数据库只存原始 JSON 字符串。









