必须用 NVARCHAR(MAX) 声明 JSON 参数并先调 ISJSON() 校验,否则 JSON_VALUE 和 OPENJSON 会静默返回 NULL;JSON_VALUE 仅取标量且路径须正确转义,多字段或嵌套结构应优先用 OPENJSON WITH;对象/数组必须用 JSON_QUERY 提取。
必须用 NVARCHAR(MAX) 声明参数,且解析前一定要调 ISJSON() 校验——漏掉任一环节,JSON_VALUE 和 OPENJSON 都会静默返回 NULL,而不是报错。
NVARCHAR(MAX)
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)
JSON_VALUE 只能取标量,路径写错或类型不匹配就返回 NULL
它只接受指向字符串、数字、布尔或 null 的路径;一旦路径指向对象(如 $.address)或数组(如 $.tags),结果就是 NULL,不是函数失效,而是语义不匹配。
中文键名必须转义:'$.["收货地址"]',不能写 '$.收货地址'。
数组元素用方括号:'$[0].amount' 提取第一个订单金额。
返回值默认是 NVARCHAR(4000),字段可能超长时要显式转换:CAST(JSON_VALUE(@json, '$.desc') AS NVARCHAR(MAX))。
JSON_VALUE(@json, '$.name') → 返回字符串JSON_VALUE(@json, '$.address') → 若 address 是对象,返回 NULL,别误以为“字段为空”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')
OPENJSON(@json) 不加 WITH,或 WITH 里写 'user.name'(缺 $)ERROR ON ERROR 到关键 JSON_VALUE 路径里,比如 JSON_VALUE(@json, '$.user.profile.phone' ERROR ON ERROR),一错立刻中断JSON_QUERY 当 JSON_VALUE 用如果 JSON 里某个字段是对象或数组(比如 "tags": ["a","b"]),用 JSON_VALUE 提取会返回 NULL;必须用 JSON_QUERY 保留原始结构。JSON_VALUE(@j, '$.tags') → NULLJSON_QUERY(@j, '$.tags') → ["a","b"](原样字符串,无额外引号)
拼接进新 JSON 时尤其要注意:CONCAT('{ "list": ', JSON_QUERY(@j, '$.tags'), ' }') 安全;误用 JSON_VALUE 会导致变成 "list": "["a","b"]",前端 JSON.parse() 直接报错。
JSON_VALUE
JSON_QUERY
CROSS APPLY 链越长,容易漏掉某一层的 OPENJSON 展开