Published on

3. FOR XML (SQL Server) : SELECT 查询将结果作为行集返回

Authors

环境要求

基本初识

在 FOR XML 子句中,有 RAWAUTOEXPLICITPATH 四种模式。

RAW 模式:

RAW 模式在 SELECT 语句返回的行集中为每个行生成一个行元素。 可以通过编写嵌套 FOR XML 查询来生成 XML 层次结构。

AUTO 模式:

AUTO 模式将基于指定 SELECT 语句的方式来使用试探性方法在 XML 结果中生成嵌套。 您对生成的 XML 的形状具有最低限度的控制能力。 除了 AUTO 模式的试探性方法生成的 XML 形状之外,还可以编写 FOR XML 查询来生成 XML 层次结构。

EXPLICIT模式:

EXPLICIT 模式允许对 XML 的形状进行更多控制。 您可以随意混合属性和元素来确定 XML 的形状。

PATH模式:

PATH 模式与嵌套 FOR XML 查询功能一起以较简单的方式提供了 EXPLICIT 模式的灵活性。

测试数据库:

CREATE TABLE [dbo].[userTable](
	[id] [nvarchar](50) NULL,
	[encode] [nvarchar](50) NULL,
	[name] [nvarchar](50) NULL
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[userTable] ADD  CONSTRAINT [DF_user_id]  DEFAULT (newid()) FOR [id]
GO

INSERT [dbo].[userTable] ([id], [encode], [name]) VALUES (N'1A074FE5-BAB3-4B71-932D-393387E94B5F', N'001', N'张三')
GO
INSERT [dbo].[userTable] ([id], [encode], [name]) VALUES (N'F75F5FA1-D8A1-4076-B840-99941DB9038F', N'002', N'李四')
GO
INSERT [dbo].[userTable] ([id], [encode], [name]) VALUES (N'FF611E9B-2D28-4C53-A4DE-FE67A16D4FD4', N'003', N'王五')
GO
INSERT [dbo].[userTable] ([id],[encode], [name]) VALUES (N'79BB7B1A-CAC9-4D2E-A0CE-56C91F8FF76A', N'004',null)

idencodename
1A074FE5-BAB3-4B71-932D-393387E94B5F001张三
F75F5FA1-D8A1-4076-B840-99941DB9038F002李四
FF611E9B-2D28-4C53-A4DE-FE67A16D4FD4003王五
79BB7B1A-CAC9-4D2E-A0CE-56C91F8FF76A004NULL

使用示例:

将查询结果作为行集返回,即只有一个查询行,此行只有一个查询列。 多个指令可使用 逗号 分割开。

RAW模式

示例一 : 基本使用
select * from userTable  for xml raw ;
<!--普通使用-->
<row id="1A074FE5-BAB3-4B71-932D-393387E94B5F" encode="001" name="张三" />
<row id="F75F5FA1-D8A1-4076-B840-99941DB9038F" encode="002" name="李四" />
<row id="FF611E9B-2D28-4C53-A4DE-FE67A16D4FD4" encode="003" name="王五" />
<row id="79BB7B1A-CAC9-4D2E-A0CE-56C91F8FF76A" encode="004" />
示例二 : ELEMENTS 指令
select * from userTable for xml raw,ELEMENTS  ;
<!--ELEMENTS指令:检索以元素为中心的 XML-->
<row>
  <id>1A074FE5-BAB3-4B71-932D-393387E94B5F</id>
  <encode>001</encode>
  <name>张三</name>
</row>
<row>
  <id>F75F5FA1-D8A1-4076-B840-99941DB9038F</id>
  <encode>002</encode>
  <name>李四</name>
</row>
<row>
  <id>FF611E9B-2D28-4C53-A4DE-FE67A16D4FD4</id>
  <encode>003</encode>
  <name>王五</name>
</row>
<row>
  <id>79BB7B1A-CAC9-4D2E-A0CE-56C91F8FF76A</id>
  <encode>004</encode>
</row>
示例三 : XSINIL 添加指令 ELEMENTS
select * from userTable for xml raw,ELEMENTS XSINIL ;
<!--XSINIL 添加指令 ELEMENTS:对为 Null 值的数据生成XML-->
<row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <id>1A074FE5-BAB3-4B71-932D-393387E94B5F</id>
  <encode>001</encode>
  <name>张三</name>
</row>
<row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <id>F75F5FA1-D8A1-4076-B840-99941DB9038F</id>
  <encode>002</encode>
  <name>李四</name>
</row>
<row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <id>FF611E9B-2D28-4C53-A4DE-FE67A16D4FD4</id>
  <encode>003</encode>
  <name>王五</name>
</row>
<row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <id>79BB7B1A-CAC9-4D2E-A0CE-56C91F8FF76A</id>
  <encode>004</encode>
  <name xsi:nil="true" />
</row>
示例四 : XMLDATA 指令
select * from userTable for xml raw,XMLDATA  ;
<!-- 返回描述文档结构的 XML-DATA 架构 -->
<Schema name="Schema1" xmlns="urn:schemas-microsoft-com:xml-data" xmlns:dt="urn:schemas-microsoft-com:datatypes">
  <ElementType name="row" content="empty" model="closed">
    <AttributeType name="id" dt:type="string" />
    <AttributeType name="encode" dt:type="string" />
    <AttributeType name="name" dt:type="string" />
    <attribute type="id" />
    <attribute type="encode" />
    <attribute type="name" />
  </ElementType>
</Schema>
<row xmlns="x-schema:#Schema1" id="1A074FE5-BAB3-4B71-932D-393387E94B5F" encode="001" name="张三" />
<row xmlns="x-schema:#Schema1" id="F75F5FA1-D8A1-4076-B840-99941DB9038F" encode="002" name="李四" />
<row xmlns="x-schema:#Schema1" id="FF611E9B-2D28-4C53-A4DE-FE67A16D4FD4" encode="003" name="王五" />
<row xmlns="x-schema:#Schema1" id="79BB7B1A-CAC9-4D2E-A0CE-56C91F8FF76A" encode="004" />
其他
  • FOR XML RAW ('xx'): 重命名行元素。
  • ROOT 指令: 为 FOR XML 生成的 XML 指定根元素。比如:ROOT('MyRoot');
  • XMLSCHEMA 指令: 返回 XSD 架构 。比如:可以使用 XMLSCHEMA ('urn:example.com') 格式指定命名空间 。
  • BINARY BASE64 指令: 返回在 varbinary(max)、binary 类型列中存储的 以 base64 编码格式返回二进制数据。

AUTO 模式

示例一:
select * from userTable x for xml AUTO;
<!-- 可以为表设置别名 同时结合上述指令  -->
<userTable id="1A074FE5-BAB3-4B71-932D-393387E94B5F" encode="001" name="张三" />
<userTable id="F75F5FA1-D8A1-4076-B840-99941DB9038F" encode="002" name="李四" />
<userTable id="FF611E9B-2D28-4C53-A4DE-FE67A16D4FD4" encode="003" name="王五" />
<userTable id="79BB7B1A-CAC9-4D2E-A0CE-56C91F8FF76A" encode="004" />
示例二:

先指定 OrderHeader 表中的列,再指定 Cust 表中的列, 因此,将创建第一个 <OrderHeader> 元素,然后将 <Cust> 子元素添加到其中。

elect OrderHeader.CustomerID,
       OrderHeader.SalesOrderID,
       OrderHeader.Status,
       Cust.CustomerID,
       Cust.CustomerType
from Sales.Customer Cust, Sales.SalesOrderHeader OrderHeader
where Cust.CustomerID = OrderHeader.CustomerID
for xml auto; 
<!-- 可结合 ELEMENTS 等其他指令-->
<OrderHeader CustomerID="1" SalesOrderID="43860" Status="5">
  <Cust CustomerID="1" CustomerType="S" />
</OrderHeader>
...

PATH 模式

示例一
select * from userTable   for xml PATH 
<row>
  <id>1A074FE5-BAB3-4B71-932D-393387E94B5F</id>
  <encode>001</encode>
  <name>张三</name>
</row>
<row>
  <id>F75F5FA1-D8A1-4076-B840-99941DB9038F</id>
  <encode>002</encode>
  <name>李四</name>
</row>
<row>
  <id>FF611E9B-2D28-4C53-A4DE-FE67A16D4FD4</id>
  <encode>003</encode>
  <name>王五</name>
</row>
<row>
  <id>79BB7B1A-CAC9-4D2E-A0CE-56C91F8FF76A</id>
  <encode>004</encode>
</row>
示例二
select * from userTable  for xml PATH('') ;
<id>1A074FE5-BAB3-4B71-932D-393387E94B5F</id>
<encode>001</encode>
<name>张三</name>
<id>F75F5FA1-D8A1-4076-B840-99941DB9038F</id>
<encode>002</encode>
<name>李四</name>
<id>FF611E9B-2D28-4C53-A4DE-FE67A16D4FD4</id>
<encode>003</encode>
<name>王五</name>
<id>79BB7B1A-CAC9-4D2E-A0CE-56C91F8FF76A</id>
<encode>004</encode>
示例三

如果列名称以符号 (@) 开头,并且不包含斜杠标记 (/),则会创建具有相应列值的元素的属性 row 在对应的语句中,可根据不同模式对表名、列名进行别名的设置而得到相应得到XML结构

select id as '@part',encode as '@code',name  from userTable  for xml PATH
<row part="1A074FE5-BAB3-4B71-932D-393387E94B5F" code="001">
  <name>张三</name>
</row>
<row part="F75F5FA1-D8A1-4076-B840-99941DB9038F" code="002">
  <name>李四</name>
</row>
<row part="FF611E9B-2D28-4C53-A4DE-FE67A16D4FD4" code="003">
  <name>王五</name>
</row>
<row part="79BB7B1A-CAC9-4D2E-A0CE-56C91F8FF76A" code="004" />
示例四

如果列名不以符号 () @ 开头,但包含斜杠标记 (/) ,则列名表示 XML 层次结构。

select ID as 'ID1/ID2',ENCODE,NAME  from userTable  for xml PATH
<row>
  <ID1>
    <ID2>1A074FE5-BAB3-4B71-932D-393387E94B5F</ID2>
  </ID1>
  <ENCODE>001</ENCODE>
  <NAME>张三</NAME>
</row>
<row>
  <ID1>
    <ID2>F75F5FA1-D8A1-4076-B840-99941DB9038F</ID2>
  </ID1>
  <ENCODE>002</ENCODE>
  <NAME>李四</NAME>
</row>
<row>
  <ID1>
    <ID2>FF611E9B-2D28-4C53-A4DE-FE67A16D4FD4</ID2>
  </ID1>
  <ENCODE>003</ENCODE>
  <NAME>王五</NAME>
</row>
<row>
  <ID1>
    <ID2>79BB7B1A-CAC9-4D2E-A0CE-56C91F8FF76A</ID2>
  </ID1>
  <ENCODE>004</ENCODE>
</row>
示例五

如果指定的列名是通配符 (*) ,则插入该列的内容就好像没有指定列名一样。 如果此列不是xml 类型的列,则此列的内容将作为文本节点插入.

select ID as '*',ENCODE,NAME  from userTable  for xml PATH 
<row>1A074FE5-BAB3-4B71-932D-393387E94B5F<ENCODE>001</ENCODE><NAME>张三</NAME></row>
<row>F75F5FA1-D8A1-4076-B840-99941DB9038F<ENCODE>002</ENCODE><NAME>李四</NAME></row>
<row>FF611E9B-2D28-4C53-A4DE-FE67A16D4FD4<ENCODE>003</ENCODE><NAME>王五</NAME></row>
<row>79BB7B1A-CAC9-4D2E-A0CE-56C91F8FF76A<ENCODE>004</ENCODE></row>
示例六

如果列名是某个 XPath 节点测试,将如下表所示映射该列的内容。 如果列名是某个 XPath 节点测试,则该列的内容将映射到相应的节点。 如果该列的 SQL 类型是 xml,将返回一个错误。

列名行为
text()对于名为 text() 的列,该列中的字符串值将被添加为文本节点。
comment()对于名为 comment() 的列,该列中的字符串值将被添加为 XML 注释。
node()对于节点名称 () 的列,结果与列名称是通配符 () * 时的结果相同。
处理指令(名称)如果列名为处理指令,该列中的字符串值将被添加为此处理指令目标名称的 PI 值。
select ID as 'text()',ENCODE as 'comment()',NAME as 'node()'  from userTable  for xml PATH 
<row>1A074FE5-BAB3-4B71-932D-393387E94B5F<!--001-->张三</row>
<row>F75F5FA1-D8A1-4076-B840-99941DB9038F<!--002-->李四</row>
<row>FF611E9B-2D28-4C53-A4DE-FE67A16D4FD4<!--003-->王五</row>
<row>79BB7B1A-CAC9-4D2E-A0CE-56C91F8FF76A<!--004--></row>
示例七
select ','+ID   from userTable  for xml PATH('')
,1A074FE5-BAB3-4B71-932D-393387E94B5F,F75F5FA1-D8A1-4076-B840-99941DB9038F,FF611E9B-2D28-4C53-A4DE-FE67A16D4FD4,79BB7B1A-CAC9-4D2E-A0CE-56C91F8FF76A

EXPLICIT 模式

具体可参阅微软官方文档