示例:使用 AUTO 模式

以下示例演示了 AUTO 模式的使用。 其中许多查询针对自行车制造指令 XML 文档指定,这些文档存储在 AdventureWorks2012 示例数据库中 ProductModel 表的“指令”列中。

示例:检索客户、订单和订单详细信息

此查询检索特定客户的客户、订单和订单详细信息信息。

USE AdventureWorks2012;  
GO  
SELECT Cust.CustomerID,   
       OrderHeader.CustomerID,  
       OrderHeader.SalesOrderID,   
       Detail.SalesOrderID, Detail.LineTotal, Detail.ProductID,   
       Product.Name,  
       Detail.OrderQty  
FROM Sales.Customer AS Cust  
INNER JOIN Sales.SalesOrderHeader AS OrderHeader   
    ON Cust.CustomerID = OrderHeader.CustomerID  
INNER JOIN Sales.SalesOrderDetail AS Detail  
    ON OrderHeader.SalesOrderID = Detail.SalesOrderID  
INNER JOIN Production.Product AS Product  
    ON Product.ProductID = Detail.ProductID  
WHERE Cust.CustomerID IN (29672, 29734)  
ORDER BY OrderHeader.CustomerID,  
         OrderHeader.SalesOrderID  
FOR XML AUTO;  

由于查询标识了 CustOrderHeaderDetailProduct 表的别名,相应的元素通过 AUTO 模式生成。 同样,由 SELECT 子句中指定的列标识表的顺序决定了这些元素的层次结构。

下面是部分结果:

<Cust CustomerID="29672">

<OrderHeader CustomerID="29672" SalesOrderID="43660">

<Detail SalesOrderID="43660" LineTotal="874.794000" ProductID="758" OrderQty="1">

<Product Name="Road-450 Red, 52" />

</Detail>

<Detail SalesOrderID="43660" LineTotal="419.458900" ProductID="762" OrderQty="1">

<Product Name="Road-650 Red, 44" />

</Detail>

</OrderHeader>

<OrderHeader CustomerID="29672" SalesOrderID="47660">

<Detail SalesOrderID="47660" LineTotal="469.794000" ProductID="765" OrderQty="1">

<Product Name="Road-650 Black, 58" />

</Detail>

</OrderHeader>

<OrderHeader CustomerID="29672" SalesOrderID="49857">

<Detail SalesOrderID="49857" LineTotal="44.994000" ProductID="852" OrderQty="1">

<Product Name="Women's Tights, S" />

</Detail>

</OrderHeader>

...

</Cust>

示例:指定 GROUP BY 和聚合函数

以下查询返回单个客户 ID 以及客户请求的订单数。

USE AdventureWorks2012;  
GO  
SELECT C.CustomerID, COUNT(*) AS NoOfOrders  
FROM Sales.Customer AS C  
INNER JOIN Sales.SalesOrderHeader AS SOH  
On C.CustomerID = SOH.CustomerID  
GROUP BY C.CustomerID  
FOR XML AUTO;This is the partial result:  

<I CustomerID="11000" NoOfOrders="3" />

<I CustomerID="11001" NoOfOrders="3" />

...

示例:在 AUTO 模式下指定计算列

此查询返回串联的单个客户名称和订单信息。 由于计算列被分配给当时遇到的最内部级别,因此在这个示例中,<SOH> 元素位于该级别。 串联的客户名称将添加为结果中元素的属性 <SOH> 。

USE AdventureWorks2012;  
GO  
SELECT P.FirstName + ' ' + P.LastName AS Name,  
       SOH.SalesOrderID  
FROM Sales.Customer AS C  
INNER JOIN Sales.SalesOrderHeader AS SOH  
    ON  C.CustomerID = SOH.CustomerID  
INNER JOIN Person.Person AS P  
    ON P.BusinessEntityID = C.PersonID  
FOR XML AUTO;  

下面是部分结果:

<SOH Name="Jon Yang" SalesOrderID="43793" />  
<SOH Name="Eugene Huang" SalesOrderID="43767" />  

要检索具有Name属性的<IndividualCustomer>元素,该属性包含每个销售订单标头信息作为子元素,请使用子选择的方法重写查询。 内部查询创建一个临时 IndividualCustomer 表,该表包含计算得出的、含有各个客户名称的列。 接下来,此表与 SalesOrderHeader 表结合以获取结果。

请注意,Sales.Customer 表存储了单个客户的信息,包括该客户的 PersonID 值。 PersonID然后,这将用于从Person.Person表中查找联系人姓名。

SELECT IndividualCustomer.Name, SOH.SalesOrderID  
FROM (SELECT FirstName+ ' '+LastName AS Name, C.PersonID, C.CustomerID  
      FROM Sales.Customer AS C, Person.Person AS P  
      WHERE C.PersonID = P.BusinessEntityID) AS IndividualCustomer  
LEFT OUTER JOIN  Sales.SalesOrderHeader AS SOH  
   ON IndividualCustomer.CustomerID = SOH.CustomerID  
ORDER BY IndividualCustomer.CustomerID, SOH.CustomerIDFOR XML AUTO;  

下面是部分结果:

<IndividualCustomer Name="Jon Yang">

<SOH SalesOrderID="43793" />

<SOH SalesOrderID="51522" />

<SOH SalesOrderID="57418" />

</IndividualCustomer>

...

...

示例:返回二进制数据

此查询从 ProductPhoto 表中返回产品照片。 ThumbNailPhotoProductPhoto表中的varbinary(max)列。 默认情况下, AUTO 模式返回给二进制数据,该引用是执行查询的数据库虚拟根的相对 URL。 ProductPhotoID必须指定键属性才能标识图像。 在本示例中,当检索图像引用时,还必须在 SELECT 子句中指定表的主键,以便唯一标识数据行。

SELECT ProductPhotoID, ThumbNailPhoto  
FROM   Production.ProductPhoto   
WHERE ProductPhotoID=70  
FOR XML AUTO;  

结果如下:

-- result

<Production.ProductPhoto

ProductPhotoID="70"

ThumbNailPhoto= "dbobject/Production.ProductPhoto[@ProductPhotoID='70']/@ThumbNailPhoto" />

使用 BINARY BASE64 选项执行相同的查询。 查询以 base64 编码格式返回二进制数据。

SELECT ProductPhotoID, ThumbNailPhoto  
FROM   Production.ProductPhoto   
WHERE ProductPhotoID=70  
FOR XML AUTO, BINARY BASE64;  

结果如下:

-- result

<Production.ProductPhoto ProductPhotoID="70" ThumbNailPhoto="Base64 encoded photo" />

默认情况下,使用 AUTO 模式检索二进制数据时,将返回对执行查询的数据库虚拟根目录的相对 URL 的引用,而不是二进制数据。 如果未指定 BINARY BASE64 选项,将发生这种情况。

当 AUTO 模式返回对二进制数据的 URL 引用时,如果查询中指定的表或列名与数据库中的表或列名不匹配,查询将执行。 但是,引用中返回的事例将不一致。 例如:

SELECT ProductPhotoID, ThumbnailPhoto  
FROM   Production.ProductPhoto   
WHERE  ProductPhotoID=70  
FOR XML AUTO;  

结果如下:

<Production.PRODUCTPHOTO

PRODUCTPHOTOID="70"

THUMBNAILPHOTO= "dbobject/Production.PRODUCTPHOTO[@ProductPhotoID='70']/@ThumbNailPhoto" />

尤其是在针对区分大小写的数据库执行 dbobject 查询时,此问题尤其如此。 为了避免这种情况,查询中指定的表名或列名的大小写应与数据库中的表名或列名的大小写相匹配。

示例:了解编码

此示例显示结果中发生的各种编码。

创建此表:

CREATE TABLE [Special Chars] (Col1 char(1) primary key, [Col#&2] varbinary(50));  

将以下数据添加到表中:

INSERT INTO [Special Chars] VALUES ('&', 0x20), ('#', 0x20);  

此查询从表返回数据。 指定 FOR XML AUTO 模式。 二进制数据作为引用返回。

SELECT * FROM [Special Chars] FOR XML AUTO;  

结果如下:

<Special_x0020_Chars

Col1="#"

Col_x0023__x0026_2="dbobject/Special_x0020_Chars[@Col1='#']/@Col_x0023__x0026_2"

/>

<Special_x0020_Chars

Col1="&"

Col_x0023__x0026_2="dbobject/Special_x0020_Chars[@Col1='&']/@Col_x0023__x0026_2"

/>

这是对结果中的特殊字符进行编码的过程:

  • 在查询结果中,返回的元素和属性名称中的特殊 XML 和 URL 字符使用相应的 Unicode 字符的十六进制值进行编码。 在上一个结果中,元素名称<Special Chars>返回为 .<Special_x0020_Chars> 属性名称<Col#&2>返回为 .<Col_x0023__x0026_2> XML 和 URL 特殊字符都进行编码。

  • 如果元素或特性的值包含五个标准 XML 字符实体中的任何一个('、“”、 <和 >&),则这些特殊 XML 字符始终使用 XML 字符编码进行编码。 在上一个结果中,属性<Col1>的值&被编码为&。 但是,#字符保持不变,因为它是有效的 XML 字符,而不是特殊的 XML 字符。

  • 如果元素或属性的值包含 URL 中具有特殊含义的任何特殊 URL 字符,则它们仅在 DBOBJECT URL 值中编码,并且仅在特殊字符是表或列名的一部分时才进行编码。 在结果中,作为表名Col#&2一部分的字符#编码为 _x0023_ in the DBOJBECT URL

另请参阅

将 AUTO 模式与 FOR XML 配合使用