Up to this point, you have been using FOR XML
to compose XML from rows of data, but what if you already have XML data
and want to shred it back into relational data? SQL Server 2000
introduced a feature called OPENXML for this purpose. The OPENXML
system function is designed for this purpose, and allows an XML
document file to be shredded into T-SQL rows as we’ll explain next.
Since the introduction of the native xml data type in SQL Server 2005, XQuery (covered in the next section) offers even more choices for extracting data from XML input.
To shred data XML into relational rows using OPENXML, you first create a handle to the XML document using the system stored procedure sp_xml_preparedocument.
This system-stored procedure takes an XML document and creates a
representation that you can reference using a special handle, which it
returns via an OUTPUT parameter. OPENXML uses this handle along with a specified path and behaves like a database view to the XML data, so you simply choose SELECT from the OPENXML function just as you would SELECT from a table or a view. The code in Example 1 shows an example of OPENXML in action.
Example 1. Using FOR XML AUTO with ELEMENTS to produce element-based hierarchical XML.
DECLARE @handle int
DECLARE @OrdersXML varchar(max)
SET @OrdersXML = '
<Orders>
<Customer CustomerID="HERBC" ContactName="Charlie Herb">
<Order CustomerID="HERBC" EmployeeID="5" OrderDate="2011-11-04">
<OrderDetail OrderID="10248" ProductID="16" Quantity="12"/>
<OrderDetail OrderID="10248" ProductID="32" Quantity="10"/>
</Order>
<Order CustomerID="HERBC" EmployeeID="2" OrderDate="2011-11-16">
<OrderDetail OrderID="10283" ProductID="99" Quantity="3"/>
</Order>
</Customer>
<Customer CustomerID="HINKM" ContactName="Matt Hink">
<Order CustomerID="HINKM" EmployeeID="3" OrderDate="2011-11-23">
<OrderDetail OrderID="10283" ProductID="99" Quantity="3"/>
</Order>
</Customer>
</Orders>'
-- Get a handle onto the XML document
EXEC sp_xml_preparedocument @handle OUTPUT, @OrdersXML
-- Use the OPENXML rowset provider against the handle to parse/query the XML
SELECT *
FROM OPENXML(@handle, '/Orders/Customer/Order')
WITH (
CustomerName varchar(max) '../@ContactName',
OrderDate date)
This code allows you to query and work with the XML text as if it were relational data. The output looks like this:
CustomerName OrderDate
--------------- --------------
Charlie Herb 2011-11-04
Charlie Herb 2011-11-16
Matt Hink 2011-11-23
This code first calls sp_xml_preparedocument to get a handle over the XML of customer orders. The handle is passed as the first parameter to OPENXML. The second parameter is an XPath expression that specifies the row pattern, and this identifies the nodes within the XML that are to be processed as rows. In this example, the XPath expression /Orders/Customer/Order
drills down to the order level for each customer. There are three
orders in the XML, so the query produces three rows with order dates
(one for each order). The customer name is not available at the order
level; it must be retrieved by reaching “up” one level for the Customer element’s ContactName attribute using a column pattern. This is achieved using the WITH clause. In this example, the CustomerName column is based on the column pattern ../@ContactName to obtain the ContactName attribute (remember that in XPath an @-symbol means “attribute”) from the parent Customer node (as denoted by the ../ path syntax).