FOR XML 查询中的 TYPE 指令

适用于:SQL ServerAzure SQL 数据库Azure SQL 托管实例

SQL Server 支持 xml (Transact-SQL) 数据类型,使你可以通过指定 TYPE 指令请求将 FOR XML 查询的结果作为 xml 返回。 这样您便可以在服务器上处理 FOR XML 查询的结果。 例如,可以对其指定 Xquery,将结果分配给 xml 类型变量,或编写 嵌套 FOR XML 查询

注意

SQL Server 将 xml 数据类型实例数据作为不同服务器构造(例如使用 TYPE 指令的 FOR XML 查询,或在其中使用 xml 数据类型返回 SQL 表列和输出参数中的 XML 实例数据值的 FOR XML 查询)的结果返回到客户端。 在客户端应用程序代码中,ADO.NET 提供程序请求从服务器以二进制编码发送此 xml 数据类型信息。 但是,如果使用的是不带 TYPE 指令的 FOR XML,则 XML 数据将以字符串类型返回。 在任何情况下,客户端访问接口都始终能够处理其中任一种形式的 XML 内容。 请注意,不带 TYPE 指令的顶级 FOR XML 不能与游标一起使用。

示例

以下示例说明了带 FOR XML 查询的 TYPE 指令的用法。

作为 xml 类型检索 FOR XML 查询结果

下面的查询检索 Contacts 表中的客户联系信息。 由于在 TYPE 中指定了 FOR XML指令,因此返回的结果的类型为 xml

USE AdventureWorks2022;
Go
SELECT BusinessEntityID, FirstName, LastName
FROM Person.Person
ORDER BY BusinessEntityID
FOR XML AUTO, TYPE;

下面是部分结果:

<Person.Person BusinessEntityID="1" FirstName="Ken" LastName="Sánchez"/>
<Person.Person BusinessEntityID="2" FirstName="Terri" LastName="Duffy"/>
...

将 FOR XML 查询结果赋给 xml 类型变量

在下面的示例中,一个 FOR XML 结果被赋给一个 xml 类型变量 @x。 该查询从 BusinessEntityIDxml FirstNameLastName列检索联系信息(如 AdditionalContactInfoTYPE和其他电话号码)。 由于 FOR XML 子句指定了 TYPE 指令,因此 XML 返回为 xml 类型并赋给某个变量。

USE AdventureWorks2022;
GO
DECLARE @x xml;
SET @x = (
   SELECT BusinessEntityID,
          FirstName,
          LastName,
          AdditionalContactInfo.query('
declare namespace aci="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactInfo";
declare namespace act="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes";
              //act:telephoneNumber/act:number') as MorePhoneNumbers
   FROM Person.Person
   FOR XML AUTO, TYPE);
SELECT @x;
GO

查询 FOR XML 查询的结果

FOR XML 查询返回 XML。 因此,可以将 xml 类型方法(例如 query()value())应用于 FOR XML 查询返回的 XML 结果。

在下面的查询中, query() xml 数据类型的 方法用于查询 FOR XML 查询的结果。 有关详细信息,请参阅 query() 方法(xml 数据类型)

USE AdventureWorks2022;
GO
SELECT (SELECT BusinessEntityID, FirstName, LastName, AdditionalContactInfo.query('
DECLARE namespace aci="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactInfo";
DECLARE namespace act="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes";
//act:telephoneNumber/act:number
') AS PhoneNumbers
FROM Person.Person
FOR XML AUTO, TYPE).query('/Person.Person[1]');

内部 SELECT ... FOR XML 查询返回 xml 类型结果,外部 SELECTquery() 方法应用于该 xml 类型。 请注意指定的 TYPE 指令。

结果如下:

<Person.Person BusinessEntityID="1" FirstName="Ken" LastName="Sánchez">
  <PhoneNumbers>
    <act:number xmlns:act="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes">111-111-1111</act:number>
    <act:number xmlns:act="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes">112-111-1111</act:number>
  </PhoneNumbers>
</Person.Person>

在下面的查询中, value() xml 数据类型的 方法用于检索 SELECT...FOR XML 查询返回的 XML 结果中的值。 有关详细信息,请参阅 value() 方法(xml 数据类型)

USE AdventureWorks2022;
GO
DECLARE @FirstPhoneFromAdditionalContactInfo varchar(40);
SELECT @FirstPhoneFromAdditionalContactInfo =
( SELECT BusinessEntityID, FirstName, LastName, AdditionalContactInfo.query('
declare namespace aci="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactInfo";
declare namespace act="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes";
   //act:telephoneNumber/act:number
   ') AS PhoneNumbers
   FROM Person.Person Contact
   FOR XML AUTO, TYPE).value('
declare namespace act="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes";
  /Contact[@BusinessEntityID="1"][1]/PhoneNumbers[1]/act:number[1]', 'varchar(40)'
);
SELECT @FirstPhoneFromAdditionalContactInfo;

value() 方法中的 XQuery 路径表达式检索 BusinessEntityID1的客户联系人的第一个电话号码。

注意

如果未指定 TYPE 指令,则返回的 FOR XML 查询结果的类型为 nvarchar(max)

在 INSERT、UPDATE 和 DELETE 中使用 FOR XML 查询结果 (Transact-SQL DML)

下面的示例说明了如何在数据操作语言 (DML) 语句中使用 FOR XML 查询。 在此示例中, FOR XML 返回 xml 类型的实例。 INSERT 语句将此 XML 插入表中。

CREATE TABLE T1(intCol int, XmlCol xml);
GO
INSERT INTO T1
VALUES(1, '<Root><ProductDescription ProductModelID="1" /></Root>');
GO

CREATE TABLE T2(XmlCol xml)
GO
INSERT INTO T2(XmlCol)
SELECT (SELECT XmlCol.query('/Root')
        FROM T1
        FOR XML AUTO,TYPE);
GO

另请参阅