FOR XML PATH 的使用

本文深入解析SQL Server中FORXMLPATH函数的用法,通过多个实例展示了如何利用此函数将查询结果集以XML形式呈现,并详细解释了参数设置、节点名称、属性等关键概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

FOR XML PATH:将查询出来的结果集以 XML 的形式显示,使用 FOR XML PATH 可以简化我们的查询语句实现一些以前可能需要借助函数或存储过程来完成的工作。


创建测试表
IF NOT EXISTS (SELECT NAME FROM SYSOBJECTS WHERE NAME ='tbl_XMLPath' AND OBJECTPROPERTY(ID, 'ISTABLE') = 1)
BEGIN
  CREATE TABLE tbl_XMLPath(
    IID INT IDENTITY(1, 1) NOT NULL,
    cName VARCHAR(20), 
    cMemo VARCHAR(200)
  )
END;
GO


插入测试数据
INSERT INTO tbl_XMLPath(cName, cMemo)
SELECT '张三', 'AAA' 
UNION SELECT '李四', 'BBB' 
UNION SELECT '王五', 'CCC' 
UNION SELECT '赵六', 'DDD'
GO


查询1:简单的使用 FOR XML PATH
SELECT * FROM tbl_XMLPath FOR XML PATH 
/*
<row>
  <IID>1</IID>
  <cName>李四</cName>
  <cMemo>BBB</cMemo>
</row>
<row>
  <IID>2</IID>
  <cName>王五</cName>
  <cMemo>CCC</cMemo>
</row>
<row>
  <IID>3</IID>
  <cName>张三</cName>
  <cMemo>AAA</cMemo>
</row>
<row>
  <IID>4</IID>
  <cName>赵六</cName>
  <cMemo>DDD</cMemo>
</row>
*/
以下结果是以元素为中心的 XML,在该 XML 中,生成的行集中的每个列值都包在元素中。由于 SELECT 子句未指定任何列名别名,因此生成的子元素名称与 SELECT 子句中相应的列名相同。针对行集中的每一行,将添加一个 <row> 标记,<row>为默认标志。


查询2:下面的查询语句与上面查询1的结果是一样的
SELECT * FROM tbl_XMLPath FOR XML RAW, ELEMENTS;

查询3:可以选择指定行元素名称,以覆盖默认的 <row>。例如,以下查询将针对行集中的每一行返回相应的 <Person> 元素。
SELECT * FROM tbl_XMLPath FOR XML PATH('Person')
/*
<Person>
  <IID>1</IID>
  <cName>李四</cName>
  <cMemo>BBB</cMemo>
</Person>
<Person>
  <IID>2</IID>
  <cName>王五</cName>
  <cMemo>CCC</cMemo>
</Person>
<Person>
  <IID>3</IID>
  <cName>张三</cName>
  <cMemo>AAA</cMemo>
</Person>
<Person>
  <IID>4</IID>
  <cName>赵六</cName>
  <cMemo>DDD</cMemo>
</Person>
*/


查询4:如果PATH指定的是空值,将不生成行元素进行数据包装
SELECT * FROM tbl_XMLPath FOR XML PATH('')
/*
<IID>1</IID>
<cName>李四</cName>
<cMemo>BBB</cMemo>
<IID>2</IID>
<cName>王五</cName>
<cMemo>CCC</cMemo>
<IID>3</IID>
<cName>张三</cName>
<cMemo>AAA</cMemo>
<IID>4</IID>
<cName>赵六</cName>
<cMemo>DDD</cMemo>
*/


指定 XML 的节点名称,只需要在对应表列字段上进行 AS 重命名即可。若列名以 '@' 开头,且不包含斜杠标记('/'),产生的结果是改列的值将作为该行节点的属性值
查询5:演示节点重命名
SELECT cName AS '@NAME', cMemo AS 'Descriptor' FROM tbl_XMLPath FOR XML PATH('Person')
/*
<Person NAME="李四">
  <Descriptor>BBB</Descriptor>
</Person>
<Person NAME="王五">
  <Descriptor>CCC</Descriptor>
</Person>
<Person NAME="张三">
  <Descriptor>AAA</Descriptor>
</Person>
<Person NAME="赵六">
  <Descriptor>DDD</Descriptor>
</Person>
*/


查询6:为 XML 添加一个顶级的节点名称
SELECT cName AS '@NAME', cMemo AS 'Descriptor' FROM tbl_XMLPath FOR XML PATH('Person'), ROOT('ROOT')
/*
<ROOT>
  <Person NAME="李四">
    <Descriptor>BBB</Descriptor>
  </Person>
  <Person NAME="王五">
    <Descriptor>CCC</Descriptor>
  </Person>
  <Person NAME="张三">
    <Descriptor>AAA</Descriptor>
  </Person>
  <Person NAME="赵六">
    <Descriptor>DDD</Descriptor>
  </Person>
</ROOT>
*/


查询7:将 cMemo 列的列名改为“Child/Descriptor”,就会获得具有层次结构的
SELECT cName AS '@NAME', cMemo AS 'Child/Descriptor' FROM tbl_XMLPath FOR XML PATH('Person')
/*
<Person NAME="李四">
  <Child>
    <Descriptor>BBB</Descriptor>
  </Child>
</Person>
<Person NAME="王五">
  <Child>
    <Descriptor>CCC</Descriptor>
  </Child>
</Person>
<Person NAME="张三">
  <Child>
    <Descriptor>AAA</Descriptor>
  </Child>
</Person>
<Person NAME="赵六">
  <Child>
    <Descriptor>DDD</Descriptor>
  </Child>
</Person>
*/


以上是 FOR XML PATH 的简单使用,以下结合示例进行演示


示例1:将表中 cName 的所有记录存储到一个变量中
DECLARE @Str VARCHAR(200)
SET @Str = ''
SET @Str = @Str + STUFF((SELECT ',' + cName FROM tbl_XMLPath FOR XML PATH('')), 1, 1, '')
PRINT @Str
/*
李四,王五,张三,赵六
*/


--示例2:将多条记录的值合并到一条记录
INSERT INTO tbl_XMLPath
SELECT '张三', '123' 
UNION SELECT '李四', '456' 
UNION SELECT '王五', '789' 
UNION SELECT '赵六', '012'
UNION SELECT '张三', 'QWE' 
UNION SELECT '李四', 'ASD' 
UNION SELECT '王五', 'ZXC' 
UNION SELECT '赵六', 'HJK'
GO


SELECT cName,
       STUFF((SELECT ',' + cMemo FROM tbl_XMLPath WHERE cName = A.cName FOR XML PATH('')), 1, 1, '') AS cMemos
FROM tbl_XMLPath A GROUP BY cName
/*
cName                cMemos
-------------------- -----------------------
李四                   BBB,456,ASD
王五                   CCC,789,ZXC
张三                   AAA,123,QWE
赵六                   DDD,012,HJK
(4 行受影响)
*/


--删除测试表
DROP TABLE tbl_XMLPath
### SQL Server 中 FOR XML PATH 使用示例 在 SQL Server 中,`FOR XML PATH` 是一种用于生成结构化 XML 数据的方式。它允许通过指定路径表达式来自定义输出的 XML 结构[^1]。 以下是 `FOR XML PATH` 的基本语法以及一些常见的使用场景: #### 基本语法 ```sql SELECT column_name(s) FROM table_name FOR XML PATH('root_element_name') ``` 在此语法中,`'root_element_name'` 定义了每行数据对应的 XML 节点名称。如果省略该参数,则默认不会为每一行创建根节点[^2]。 --- #### 示例 1:简单查询并生成 XML 输出 假设有一个名为 `Employees` 的表,其字段包括 `EmployeeID`, `FirstName`, 和 `LastName`。可以使用如下语句将其转换为 XML 格式: ```sql SELECT EmployeeID, FirstName, LastName FROM Employees FOR XML PATH('Employee'), ROOT('Employees'); ``` 此语句的结果将是这样的 XML 树形结构: ```xml <Employees> <Employee> <EmployeeID>1</EmployeeID> <FirstName>John</FirstName> <LastName>Doe</LastName> </Employee> <Employee> <EmployeeID>2</EmployeeID> <FirstName>Jane</FirstName> <LastName>Smith</LastName> </Employee> </Employees> ``` 这里,`ROOT('Employees')` 添加了一个顶层 `<Employees>` 元素包裹所有的子节点[^3]。 --- #### 示例 2:自定义标签名称 可以通过设置列别名来控制生成的 XML 元素名称。例如: ```sql SELECT EmployeeID AS '@id', -- 将属性附加到父级元素上 FirstName AS 'Name/First', LastName AS 'Name/Last' FROM Employees FOR XML PATH('Employee'), ROOT('Employees'); ``` 上述语句将生成以下 XML: ```xml <Employees> <Employee id="1"> <Name> <First>John</First> <Last>Doe</Last> </Name> </Employee> <Employee id="2"> <Name> <First>Jane</First> <Last>Smith</Last> </Name> </Employee> </Employees> ``` 注意,在这个例子中,`@id` 表示的是一个 XML 属性而不是子元素。 --- #### 示例 3:嵌套复杂结构 当需要表示更复杂的层次关系时,可利用多层 SELECT 子查询实现嵌套效果。比如下面的例子展示了如何把部门信息和员工列表组合在一起: ```sql SELECT Department.Name AS '@name', ( SELECT Employee.FirstName, Employee.LastName FROM Employees WHERE Employees.DepartmentID = Department.ID FOR XML PATH('Member'), TYPE ) AS Members FROM Departments AS Department FOR XML PATH('Department'), ROOT('Departments'); ``` 这段代码会产生类似如下的结果: ```xml <Departments> <Department name="HR"> <Members> <Member> <FirstName>John</FirstName> <LastName>Doe</LastName> </Member> <Member> <FirstName>Jane</FirstName> <LastName>Smith</LastName> </Member> </Members> </Department> <!-- More departments --> </Departments> ``` 这里的关键词 `TYPE` 确保内部查询返回的内容作为一个整体被纳入外部查询之中。 --- #### 示例 4:无根节点的情况 如果不希望最终得到任何额外的封装标记,可以直接留空字符串作为路径值: ```sql DECLARE @TempTable TABLE (UserID INT, UserName NVARCHAR(50)); INSERT INTO @TempTable VALUES (1,'Alice'), (2,'Bob'); SELECT CAST(UserID AS VARCHAR) + '', UserName + '' FROM @TempTable FOR XML PATH(''); ``` 这会生产像这样扁平化的输出形式: ```xml <UserID>Alice</UserID><UserName></UserName><UserID>Bob</UserID><UserName></UserName> ``` 这种技巧常用来拼接纯文本串而非标准文档样式的数据。 --- ### 总结 以上就是几种典型的运用方式展示出了灵活性与强大功能所在之处——即能够按照需求灵活调整所期望获得的形式化表述内容。无论是简单的键值对还是高度定制化的树状架构都可以轻松达成目标。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值