IT tutorials
 
Database
 

SQL Server 2012 : XML and the Relational Database - Additional FOR XML Features (part 1)

7/23/2013 8:10:45 PM
- Free product key for windows 10
- Free Product Key for Microsoft office 365
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019

Just about all of the original XML support first introduced in SQL Server 2000 XML support revolves around FOR XML, a feature that is still very much underused by developers. Since then, SQL Server has enhanced FOR XML in the following ways:

  • Using the TYPE option, FOR XML can output to an xml data type (as opposed to streamed results) from a SELECT statement, which in turn allows you to nest the results of SELECT…FOR XML into another SELECT statement.

  • The FOR XML PATH option allows you to more easily shape data and produce element-based XML than the FOR XML EXPLICIT option that we just covered.

  • You can explicitly specify a ROOT element for your output.

  • You can produce element-based XML with FOR XML AUTO.

  • FOR XML can produce XML with an embedded, inferred XSD schema.

1. The TYPE Option

As of SQL Server 2005, xml is an intrinsic data type of SQL Server. Thus, you can cast the XML output from a FOR XML query directly into an xml data type instance, as opposed to streaming XML results directly or immediately to the client. You accomplish this by using the TYPE keyword after your FOR XML statement, as shown in Example 1.

Example 1. Using the TYPE option with FOR XML AUTO to cast a subquery result set as an xml data type.

SELECT
  CustomerID,
  (SELECT SalesOrderID, TotalDue, OrderDate, ShipDate
   FROM Sales.SalesOrderHeader AS OrderHeader
   WHERE CustomerID = Customer.CustomerID
   FOR XML AUTO, TYPE) AS OrderHeaders
 FROM
  Sales.Customer AS Customer
 WHERE
  CustomerID IN (11000, 11001)

This query returns two columns. The first is the integer CustomerID and the second is an OrderHeaders column of type xml. The second column is constructed by a subquery that generates XML using FOR XML AUTO, and the TYPE option casts the generated XML from the subquery into an xml data type that gets returned as the OrderHeaders column of the main query.

2. FOR XML PATH

As we already mentioned, FOR XML PATH gives you fine control over the generated XML much like FOR XML EXPLICIT does, but is much simpler to use. With FOR XML PATH, you simply assign column aliases with XPath expressions that shape your XML output, as shown in Example 2.

Example 2. Using FOR XML PATH to shape XML output with XPath-based column aliases.

SELECT
  BusinessEntityID AS [@BusinessEntityID],
  FirstName AS [ContactName/First],
  LastName AS [ContactName/Last],
  EmailAddress AS [ContactEmailAddress/EmailAddress1]
 FROM
  HumanResources.vEmployee
 FOR XML PATH('Contact')

The output looks like this:

<row BusinessEntityID="263">
  <ContactName>
    <First>Jean</First>
    <Last>Trenary</Last>
  </ContactName>
  <ContactEmailAddress>
    <EmailAddress1>[email protected]</EmailAddress1>
  </ContactEmailAddress>
</row>
<row BusinessEntityID="78">
  <ContactName>
    <First>Reuben</First>
    <Last>D'sa</Last>
  </ContactName>
  <ContactEmailAddress>
    <EmailAddress1>[email protected]</EmailAddress1>
  </ContactEmailAddress>
</row>
 :

Notice that the BusinessEntityID column is rendered as an attribute. This is because it was aliased as @BusinessEntityID, and the @-symbol in XPath means “attribute.” Also notice that the FirstName and LastName columns are rendered as First and Last elements nested within a ContactName element. This again is due to the XPath-based syntax of the column aliases, ContactName/First and ContactName/Last.

Using the TYPE option in conjunction with FOR XML PATH, you can reproduce that awful and complex query with a much simpler version, as shown in Example 3.

Example 3. Using FOR XML PATH to shape XML output for a three-level hierarchy.

SELECT
  CustomerID AS [@CustomerID],
  (SELECT
    SalesOrderID AS [@SalesOrderID],
    TotalDue AS [@TotalDue],
    OrderDate,
    ShipDate,
    (SELECT
      ProductID AS [@ProductID],
      OrderQty AS [@OrderQty],
      LineTotal AS [@LineTotal]
     FROM Sales.SalesOrderDetail
     WHERE SalesOrderID = OrderHeader.SalesOrderID
     FOR XML PATH('OrderDetail'), TYPE)
   FROM Sales.SalesOrderHeader AS OrderHeader
   WHERE CustomerID = Customer.CustomerID
   FOR XML PATH('OrderHeader'), TYPE)
 FROM Sales.Customer AS Customer
  INNER JOIN Person.Person AS Contact
   ON Contact.BusinessEntityID = Customer.PersonID
 WHERE CustomerID BETWEEN 11000 AND 11999
 FOR XML PATH ('Customer')

In this simpler version that produces the same result, subqueries are used with the XML PATH statement in conjunction with TYPE to produce element-based XML nested inside a much larger FOR XML PATH statement. This returns each separate Order for the customer as a new child node of the CustomerID node. And again, XPath syntax is used in the column aliases to define element and attribute structure in the generated XML. Here are the results of the query:

<Customer CustomerID="11480">
  <OrderHeader SalesOrderID="51053" TotalDue="2288.9187">
    <OrderDate>2007-06-28T00:00:00</OrderDate>
    <ShipDate>2007-07-05T00:00:00</ShipDate>
    <OrderDetail ProductID="779" OrderQty="1" LineTotal="2071.419600" />
  </OrderHeader>
  <OrderHeader SalesOrderID="52329" TotalDue="2552.5169">
    <OrderDate>2007-08-10T00:00:00</OrderDate>
    <ShipDate>2007-08-17T00:00:00</ShipDate>
    <OrderDetail ProductID="782" OrderQty="1" LineTotal="2294.990000" />
    <OrderDetail ProductID="870" OrderQty="1" LineTotal="4.990000" />
    <OrderDetail ProductID="871" OrderQty="1" LineTotal="9.990000" />
  </OrderHeader>
  <OrderHeader SalesOrderID="62813" TotalDue="612.1369">
    <OrderDate>2008-01-26T00:00:00</OrderDate>
    <ShipDate>2008-02-02T00:00:00</ShipDate>
    <OrderDetail ProductID="999" OrderQty="1" LineTotal="539.990000" />
    <OrderDetail ProductID="872" OrderQty="1" LineTotal="8.990000" />
    <OrderDetail ProductID="870" OrderQty="1" LineTotal="4.990000" />
  </OrderHeader>
</Customer>
<Customer CustomerID="11197">
  <OrderHeader SalesOrderID="57340" TotalDue="46.7194">
    :

If you are familiar and comfortable with XPath, you will appreciate some additional XML PATH features. You can use the following XPath node functions to further control the shape of your XML output:

  • data

  • comment

  • node

  • text

  • processing-instruction

The following example uses the data and comment methods of XPath. The data method takes the results of the underlying query and places them all inside one element. The comment method takes data and transforms it into an XML comment, as demonstrated in Example 4.

Example 4. Using FOR XML PATH with the comment and data XPath methods.

SELECT
  Customer.BusinessEntityID AS [@CustomerID],
  Customer.FirstName + ' ' + Customer.LastName AS [comment()],
  (SELECT
    SalesOrderID AS [@SalesOrderID],
    TotalDue AS [@TotalDue],
    OrderDate,
    ShipDate,
    (SELECT ProductID AS [data()]
     FROM Sales.SalesOrderDetail
     WHERE SalesOrderID = OrderHeader.SalesOrderID
     FOR XML PATH('')) AS [ProductIDs]
   FROM Sales.SalesOrderHeader AS OrderHeader
   WHERE CustomerID = Customer.BusinessEntityID
   FOR XML PATH('OrderHeader'), TYPE)
 FROM Sales.vIndividualCustomer AS Customer
 WHERE BusinessEntityID IN (11000, 11001)
 FOR XML PATH ('Customer')

As you can see from the results, the concatenated contact name becomes an XML comment, and the subquery of Product IDs is transformed into one element:

<Customer CustomerID="11000">
  <!--Mary Young-->
  <OrderHeader SalesOrderID="43793" TotalDue="3756.9890">
    <OrderDate>2005-07-22T00:00:00</OrderDate>
    <ShipDate>2005-07-29T00:00:00</ShipDate>
    <ProductIDs>771</ProductIDs>
  </OrderHeader>
  <OrderHeader SalesOrderID="51522" TotalDue="2587.8769">
    <OrderDate>2007-07-22T00:00:00</OrderDate>
    <ShipDate>2007-07-29T00:00:00</ShipDate>
    <ProductIDs>779 878</ProductIDs>
  </OrderHeader>
  <OrderHeader SalesOrderID="57418" TotalDue="2770.2682">
    <OrderDate>2007-11-04T00:00:00</OrderDate>
    <ShipDate>2007-11-11T00:00:00</ShipDate>
    <ProductIDs>966 934 923 707 881</ProductIDs>
  </OrderHeader>
</Customer>
<Customer CustomerID="11001">
  <!--Amber Young-->
  <OrderHeader SalesOrderID="43767" TotalDue="3729.3640">
    <OrderDate>2005-07-18T00:00:00</OrderDate>
       :
 
Others
 
 
 
Top 10
 
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
Technology FAQ
- Is possible to just to use a wireless router to extend wireless access to wireless access points?
- Ruby - Insert Struct to MySql
- how to find my Symantec pcAnywhere serial number
- About direct X / Open GL issue
- How to determine eclipse version?
- What SAN cert Exchange 2010 for UM, OA?
- How do I populate a SQL Express table from Excel file?
- code for express check out with Paypal.
- Problem with Templated User Control
- ShellExecute SW_HIDE
programming4us programming4us