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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值