SQL Server 2022未新增嵌套查询语法或行为,但通过JSON_OBJECT()/JSON_ARRAY()、WINDOW子句和参数敏感计划(PSP)等新特性,显著减少了对嵌套查询的依赖,提升可读性、性能与可维护性。

SQL Server 2022 本身没有为嵌套查询(nested subqueries)新增语法或行为特性。嵌套查询的语义、32层深度限制、执行顺序(由内向外)、WHERE/HAVING 中的使用方式等,与 SQL Server 2019 及更早版本完全一致。
真正值得关注的是:2022 引入的新功能,让原本依赖嵌套查询的场景有了更清晰、更高效、更可读的替代方案——这些不是“嵌套查询的新特性”,而是“让嵌套查询变得不那么必要”的新能力。
JSON_OBJECT() 和 JSON_ARRAY() 替代多层子查询拼接 JSON
过去想把员工及其技能列表、部门统计打包成 JSON,常得用 FOR JSON PATH 套多层子查询,逻辑绕、难调试。
现在直接用 JSON_OBJECT() 和 JSON_ARRAY(),避免嵌套:
SELECT
EmpID,
JSON_OBJECT(
'name': Name,
'dept': Department,
'skills': JSON_ARRAY(Skills) -- 不再需要子查询生成数组
) AS profile
FROM Employees;- 旧写法需在
FOR JSON PATH外层再套一层子查询来聚合技能;新函数一步到位 -
JSON_ARRAY()接收标量值或列,不支持直接传子查询结果集;若真要聚合多行(如每个员工的项目列表),仍需子查询 +FOR JSON,但已大幅减少嵌套层级 - 注意:
JSON_OBJECT()默认对NULL输出"key": null,如需跳过键值对,加ABSENT ON NULL
WINDOW 子句让窗口计算不再依赖相关子查询
想给每条记录加上“部门平均薪资”“累计销售额”这类指标,以前常用相关子查询(correlated subquery),性能差、不可复用、难维护。
SQL Server 2022 的 WINDOW 子句允许提前定义命名窗口,然后在多个窗口函数中复用:
SELECT EmpID, Name, Department, Salary, AVG(Salary) OVER dept_window AS dept_avg_salary, SUM(Salary) OVER (ORDER BY EmpID ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS running_total FROM Employees WINDOW dept_window AS (PARTITION BY Department);
- 必须确保数据库兼容级别 ≥ 160(
ALTER DATABASE DBName SET COMPATIBILITY_LEVEL = 160),否则报错Incorrect syntax near 'WINDOW' -
WINDOW子句不能和ORDER BY在同一级 SELECT 中混用(会冲突),排序应在窗口定义内部完成 - 它不改变嵌套查询能力,但让原本需要 2–3 层相关子查询实现的聚合逻辑,变成单层、声明式、可优化的写法
参数敏感计划(PSP)缓解嵌套查询引发的参数嗅探问题
嵌套查询本身不触发参数嗅探,但当它出现在存储过程中(尤其是 WHERE 条件含子查询),且子查询逻辑受输入参数影响时,整个执行计划可能因首次参数值而固化,导致后续调用性能骤降。
SQL Server 2022 的参数敏感计划自动识别这类模式,并为不同参数范围缓存多个计划:
- 无需手动加
OPTION (RECOMPILE)或拆分逻辑,系统自动处理 - 效果取决于子查询是否被判定为“参数敏感”——例如
WHERE id IN (SELECT x FROM t WHERE y = @p)中,@p若显著影响子查询返回行数,就可能触发 PSP - 可通过
sys.dm_exec_query_plan_stats查看是否启用了 PSP 计划,字段is_parameter_sensitive_plan为 1 表示启用
真正容易被忽略的点是:别为了用新特性而硬套,先判断是否真需要嵌套。比如 IN (SELECT ...) 场景,优先考虑 JOIN;多层聚合 JSON,优先用 JSON_OBJECT() + FOR JSON 组合;而复杂窗口逻辑,WINDOW 子句比相关子查询更安全、更易读。嵌套查询没变,但它的“存在理由”正在被悄悄削弱。

















