SQL Server 生成嵌套 XML 推荐用 FOR XML PATH 配合子查询:父表主查返回顶层,子表用含 TYPE 的相关子查询嵌入;FOR XML AUTO, ELEMENTS 适合简单扁平嵌套但控制力弱;EXPLICIT 用于需精确控制的复杂场景。
SQL Server 可以通过 FOR XML 子句将关系查询结果直接转换为嵌套 XML,核心在于合理使用 FOR XML EXPLICIT、FOR XML AUTO 或更推荐的 FOR XML PATH 配合子查询或 CROSS APPLY 实现层级结构。
这是最常用、可读性较好且灵活的方式。父表主查询返回顶层元素,子表通过相关子查询(用 FOR XML PATH('') 拼接或 FOR XML PATH('Item') 生成子节点)嵌入其中。
SELECT ... FOR XML PATH('Parent'), ROOT('Root') 包裹整体结构SELECT ... FROM Child WHERE Child.ParentID = Parent.ID FOR XML PATH('Child'), TYPE,TYPE 关键字确保返回 XML 类型,避免被转义为字符串AS [text()])可生成文本节点示例:订单(Orders)及其明细(OrderDetails)
SELECT
o.OrderID AS '@id',
o.OrderDate AS 'order_date',
(SELECT
d.ProductID AS '@product',
d.Quantity AS '@qty'
FROM OrderDetails d
WHERE d.OrderID = o.OrderID
FOR XML PATH('detail'), TYPE) AS 'details'
FROM Orders o
FOR XML PATH('order'), ROOT('orders');
当关联简单、层级较浅时,FOR XML AUTO, ELEMENTS 能自动按表别名生成嵌套,但需注意:它按 JOIN 顺序和表别名推断层级,不支持自定义元素名或深度控制。
SELECT 字段,不能用 *(否则列名冲突易出错)Orders o JOIN OrderDetails d),XML 中会以别名命名外层元素ELEMENTS 让字段变为子元素而非属性;加 ROOT() 补根节点示例:
SELECT o.OrderID, o.OrderDate, d.ProductID, d.Quantity FROM Orders o INNER JOIN OrderDetails d ON o.OrderID = d.OrderID FOR XML AUTO, ELEMENTS, ROOT('result');
输出中每个 下会包含多个 ,但无法控制 是否包裹在 中——这是它的局限。
当需要混合属性/元素、跨多级嵌套、动态节点名或条件节点时,EXPLICIT 提供完全控制,但语法繁琐,需严格按 Tag 和 Parent 编号组织结果集。
Tag(整数,标识节点层级)、Parent(该行节点的父 Tag 编号)、列名按 [Tag!Level!Name!Directive] 格式别名
!directive 可为 element、attribute、hide 等UNION ALL 合并不同层级的数据行,并按 ORDER BY Tag, Parent 排序保证生成顺序虽强大,但仅建议用于报表导出等需严格 XML Schema 的场景;日常开发优先选 PATH + 子查询。
生成嵌套 XML 时几个关键点容易出错:
TYPE,否则返回 NVARCHAR,特殊字符(如 &)会被转义,破坏嵌套结构WHERE 关联条件,否则产生笛卡尔积,XML 膨胀ISNULL(col, '') 或 COALESCE 处理 NULL,防止空元素缺失或生成 xsi:nil="true"(除非需要 Schema 支持)SELECT [text()]=col FOR XML PATH(''), TYPE,再在外层用 .query('data(.)') 提取(SQL Server 2005+)