必须用 OPENJSON 配合 WITH 子句展开 JSON 字段后才能高效 JOIN;裸调 OPENJSON 仅返回 key/value/type 三列,无法映射业务字段;WITH 强制声明列名与类型,类型不匹配将返回 NULL;避免在 WHERE 中直接用 JSON_VALUE 过滤,应先展开再关联;高频查询字段可用计算列加持久化索引优化;ISJSON() 必须前置过滤;嵌套数组需用 CROSS APPLY 展开;路径须以 $ 开头,索引从 0 开始;兼容级别 ≥130,输入必须为 NVARCHAR。

不能直接用 JOIN 连接 JSON 字段和关系表——必须先用 OPENJSON 展开,再做关联;否则会触发全表扫描或隐式转换,性能断崖式下跌。
OPENJSON 必须配合 WITH 子句才能 JOIN
裸调用 OPENJSON(@json) 只返回三列:key、value、type,无法映射业务字段,也就没法写 ON t.id = j.customer_id 这类条件。
-
WITH是强制项,不是可选语法糖:不声明列名和类型,就得不到结构化结果集 - 列名可以和 JSON key 不同(比如 JSON 里是
"custId",WITH里写成customer_id INT '$.custId') - 类型必须匹配:JSON 里的
"123"(字符串)用INT提取会返回NULL,不是报错
JOIN 时别在 WHERE 中用 JSON_VALUE 做过滤条件
在 WHERE 子句里写 JSON_VALUE(doc, '$.status') = 'active' 看似简洁,但 SQL Server 无法对 JSON 字段建有效索引,每次都要全表解析,查询计划里大概率出现 Table Scan。
详细的 Three.js 3D 图形参考,涵盖场景设置、相机、几何体、材质、光照、动画、控制器、加载器、数学工具和调试。
- 正确做法:先用
OPENJSON把目标字段展开为临时结果集,再JOIN或WHERE - 如果高频按某个 JSON 字段查,考虑用计算列 + 持久化索引:
ALTER TABLE Orders ADD status AS JSON_VALUE(doc, '$.status') PERSISTED,然后在status上建索引 -
ISJSON(doc) > 0要前置过滤,避免对非 JSON 内容调用 JSON 函数引发运行时错误
嵌套数组展开后 JOIN 的典型写法
假设 Orders 表有个 doc 字段存着含 items 数组的 JSON,想关联 Products 表查商品信息:
SELECT o.id, p.name, j.qty
FROM Orders o
CROSS APPLY OPENJSON(o.doc, '$.items')
WITH (
product_id INT '$.productId',
qty INT '$.quantity'
) j
INNER JOIN Products p ON p.id = j.product_id
WHERE ISJSON(o.doc) > 0;
-
CROSS APPLY是关键:它让每行Orders都能独立展开自己的items数组,生成多行中间结果 - 路径必须以
$开头,'$.items'合法,'items'直接返回空 - 数组索引从 0 开始,
'$[0].name'才是第一个元素的 name,别误写成'$[1].name'
最易被忽略的是兼容级别和数据类型:数据库兼容级别必须 ≥ 130(对应 SQL Server 2016),且所有 JSON 函数只接受 NVARCHAR 输入——哪怕源列是 VARCHAR,也得先 CAST(doc AS NVARCHAR(MAX)),否则函数静默失败或返回意外 NULL。

















