如何在SQL Server中使用嵌套子查询高效解析嵌套JSON对象?

梦雪君_9504

梦雪君_9504

2026-11-11

317人浏览

原创

SQL Server 2016+ 支持 FOR JSON PATH/AUTO 生成嵌套 JSON,但仅限两级;深层嵌套需 OPENJSON 分层解析或 CTE 分步处理,子查询必须单行单列且用 WITHOUT_ARRAY_WRAPPER 或显式别名。

如何在sql server中使用嵌套子查询高效解析嵌套json对象?

SQL Server 2016+ 必须用 OPENJSON,不能用子查询直接解析嵌套 JSON

SQL Server 不支持像 MySQL 的 JSON_OBJECT 那样在 SELECT 中直接构造嵌套结构,更不支持用普通子查询去“读取”JSON 字段里的深层字段——SELECT ... (SELECT value FROM OPENJSON(...)) 这类写法会报错或返回空,因为 OPENJSON 返回的是行集,不是标量值。真正的嵌套解析必须分层展开:先用外层 OPENJSON 解出第一层对象数组,再对每一行用 WITH 子句或嵌套 APPLY 处理子数组。

用 CROSS APPLY + OPENJSON 展开多层嵌套数组(如 tags、categories)

常见错误是把多个 OPENJSON 写成并列子查询,导致笛卡尔积膨胀。正确做法是链式 APPLY:

SELECT 
  p.id,
  p.title,
  t.[value] AS tag_name,
  c.[value] AS category_name
FROM posts p
CROSS APPLY OPENJSON(p.metadata, '$.tags') t
CROSS APPLY OPENJSON(p.metadata, '$.categories') c;

但注意:这会产生所有 tags × categories 的组合。若只需各自独立列表,应拆成两个独立子查询并用 COALESCE 补空:

  • 用 (SELECT STRING_AGG(t.[value], ',') FROM OPENJSON(p.metadata, '$.tags') WITH ([value] NVARCHAR(100) '$') t) 提取扁平字符串
  • 或用 (SELECT JSON_QUERY('[' + STRING_AGG(JSON_QUOTE(t.[value]), ',') + ']') FROM OPENJSON(...) t) 构造合法 JSON 数组
  • 若子路径不存在,OPENJSON 返回空结果集,不是 NULL —— 所以聚合函数不会报错,但需确认业务是否接受空数组

FOR JSON PATH 嵌套子查询的唯一合法写法

SQL Server 允许在主查询中用标量子查询生成 JSON 字段,但有硬性限制:子查询必须返回单行单列,且必须用 FOR JSON PATH 并显式加别名 AS [key]:

Expanso yaml-to-json
Expanso yaml-to-json

使用 Expanso Edge 管道将 YAML 输入转换为 JSON 格式。

下载
SELECT 
  id,
  title,
  (SELECT name FROM categories c WHERE c.post_id = p.id FOR JSON PATH, WITHOUT_ARRAY_WRAPPER) AS category,
  (SELECT tag FROM tags t WHERE t.post_id = p.id FOR JSON PATH) AS tags
FROM posts p;

关键点:

  • WITHOUT_ARRAY_WRAPPER 仅当确定最多匹配一行时才可用,否则会拼接成非法 JSON
  • 子查询若无结果,整个字段为 NULL,不是 [] —— 如需空数组,得套 ISNULL(..., '[]')
  • FOR JSON PATH 默认将列名转为 key,若要自定义 key 名,必须用 AS [customKey]
  • 多层嵌套超过两级(比如 post → category → department)无法用单条 FOR JSON 实现,必须用 CTE 或临时表分步处理

性能陷阱:OPENJSON 没索引,FOR JSON 不缓存

每次调用 OPENJSON 都会重新解析整个 JSON 文本,字段越长、嵌套越深,CPU 开销越大;FOR JSON 同样是运行时序列化,无法走索引。真实场景中容易忽略的点:

  • JSON 字段未建计算列或持久化视图,导致每次查询都重复解析
  • 在 WHERE 条件里用 JSON_VALUE(metadata, '$.status') 过滤,但该列没建索引,全表扫描不可避免
  • 误以为 FOR JSON 输出可被客户端复用,实际它生成的是 NVARCHAR(MAX),网络传输和内存占用翻倍
  • 混合使用 OPENJSON 和 JSON_VALUE 时,路径表达式大小写敏感('$.Tags' ≠ '$.tags'),且不自动 trim 空格

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

js json

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

2023.08.07

2315

5

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.23

3782

1

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

2023.10.13

1256

3

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

2025.09.10

4379

7

sqlserver和mysql区别
sqlserver和mysql区别

SQL Server和MySQL是两种广泛使用的关系型数据库管理系统。它们具有相似的功能和用途,但在某些方面存在一些显著的区别。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.11

6631

4

Postman身份认证怎么配置
Postman身份认证怎么配置

本专题从实际API接口调试场景出发,讲解Postman身份认证的完整配置流程,包括常见认证协议介绍、授权参数设置、访问令牌填写、OAuth 2.0授权及认证失败排查,帮助用户正确完成接口授权与访问验证。

2026.11.06

80

12

Postman请求头Headers怎么设置
Postman请求头Headers怎么设置

围绕Postman HTTP请求头配置展开,讲解Headers选项的具体使用方式,包括Key和Value参数填写、请求头信息添加、常见Header字段设置及请求头修改方法,帮助用户解决接口调试过程中遇到的请求头配置问题。

2026.11.06

40

13

Postman接口请求发送教程
Postman接口请求发送教程

详细介绍Postman接口请求的创建与发送方法,涵盖GET和POST请求、URL配置、请求参数、Headers请求头、Body请求体设置以及响应结果查看,帮助用户掌握Postman接口请求的完整操作流程。

2026.11.06

80

10

DBeaver怎么导入数据
DBeaver怎么导入数据

DBeaver数据导入专题,整理Excel、CSV、SQL、TXT等常见文件的数据导入方法,涵盖目标数据库选择、数据表创建、字段映射、数据类型设置及导入参数配置等操作,帮助用户将本地文件中的数据写入数据库,并了解批量导入、重复数据处理和导入失败等常见问题的解决方法。

2026.11.05

60

12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WEB前端教程【HTML5+CSS3+JS】
WEB前端教程【HTML5+CSS3+JS】

共101课时 | 21.3万人学习

JS进阶与BootStrap学习
JS进阶与BootStrap学习

共39课时 | 4.9万人学习