Module 18 Querying XML Data in SQL Server® 2008 R2
Module Overview Using the T-SQL FOR XML Statement Getting Started with XQuery Shredding XML
Lesson 1: Using the T-SQL FOR XML Statement Introducing the FOR XML clause Using RAW Mode Queries Using Auto Mode Queries Using Explicit Mode Queries Using Path Mode Queries Retrieving Nested XML Demonstration 1A: FOR XML Queries
Introducing the FOR XML clause Extends SELECT syntax Returns XML instead of rows and columns Is configurable to return attributes, elements, and schema Benefits client applications that work with XML Converted to XML Client Application Database Server
SELECT c.CustomerID AS CustID, soh.SalesOrderID FROM Sales.Customer AS c INNER JOIN Sales.SalesOrderHeader AS soh ON c.CustomerID = soh.CustomerID ORDER BY c.CustomerID FOR XML RAW; SELECT c.CustomerID AS CustID, soh.SalesOrderID FROM Sales.Customer AS c INNER JOIN Sales.SalesOrderHeader AS soh ON c.CustomerID = soh.CustomerID ORDER BY c.CustomerID FOR XML RAW; SELECT c.CustomerID AS CustID, soh.SalesOrderID FROM Sales.Customer AS c INNER JOIN Sales.SalesOrderHeader AS soh ON c.CustomerID = soh.CustomerID ORDER BY c.CustomerID FOR XML RAW, ELEMENTS; SELECT c.CustomerID AS CustID, soh.SalesOrderID FROM Sales.Customer AS c INNER JOIN Sales.SalesOrderHeader AS soh ON c.CustomerID = soh.CustomerID ORDER BY c.CustomerID FOR XML RAW, ELEMENTS; SELECT c.CustomerID AS CustID, soh.SalesOrderID FROM Sales.Customer AS c INNER JOIN Sales.SalesOrderHeader AS soh ON c.CustomerID = soh.CustomerID ORDER BY c.CustomerID FOR XML RAW('Order'), ROOT('Orders'); SELECT c.CustomerID AS CustID, soh.SalesOrderID FROM Sales.Customer AS c INNER JOIN Sales.SalesOrderHeader AS soh ON c.CustomerID = soh.CustomerID ORDER BY c.CustomerID FOR XML RAW('Order'), ROOT('Orders'); Using RAW Mode Queries … … Is an XML representation of a rowset Contains either elements or attributes Has optional root element and row element name … … … …
Using Auto Mode Queries SELECT Customer.CustomerID AS CustID, Customer.StoreID, [Order].SalesOrderID FROM Sales.Customer AS Customer INNER JOIN Sales.SalesOrderHeader AS [Order] ON Customer.CustomerID = [Order].CustomerID ORDER BY Customer.CustomerID FOR XML AUTO; SELECT Customer.CustomerID AS CustID, Customer.StoreID, [Order].SalesOrderID FROM Sales.Customer AS Customer INNER JOIN Sales.SalesOrderHeader AS [Order] ON Customer.CustomerID = [Order].CustomerID ORDER BY Customer.CustomerID FOR XML AUTO;
SELECT 1 AS Tag, NULL AS Parent, SalesOrderID AS [Invoice!1!InvoiceNo], OrderDate AS [Invoice!1!Date!Element] FROM SalesOrderHeader FOR XML EXPLICIT SELECT 1 AS Tag, NULL AS Parent, SalesOrderID AS [Invoice!1!InvoiceNo], OrderDate AS [Invoice!1!Date!Element] FROM SalesOrderHeader FOR XML EXPLICIT T00:00: T00:00:00... Using Explicit Mode Queries SELECT 1 AS Tag, NULL AS Parent, SalesOrderID AS [Invoice!1!InvoiceNo], OrderDate AS [Invoice!1!Date!Element] FROM Sales.SalesOrderHeader FOR XML EXPLICIT; SELECT 1 AS Tag, NULL AS Parent, SalesOrderID AS [Invoice!1!InvoiceNo], OrderDate AS [Invoice!1!Date!Element] FROM Sales.SalesOrderHeader FOR XML EXPLICIT; T00:00: T00:00:00 Allows tabular representation of XML documents TagParentInvoice!1!InvoiceNoInvoice!1!Date!Element 1NULL T00:00:00 1NULL T00:00:00 Attribute Element Allows complete control of XML format
Using Path Mode Queries SELECT p.BusinessEntityID p.FirstName "EmpName/First", p.LastName "EmpName/Last" FROM Person.Person AS p FOR XML PATH SELECT p.BusinessEntityID p.FirstName "EmpName/First", p.LastName "EmpName/Last" FROM Person.Person AS p FOR XML PATH Use XML Path Language (XPath) to specify XML format Allow creation of nested data and specify what should be exposed as an ELEMENT or an ATTRIBUTE Easier to use than EXPLICIT mode Min Su Min Su
SELECT Customer.CustomerID, Customer.TerritoryID, (SELECT SalesOrderID, [Status] FROM Sales.SalesOrderHeader AS soh WHERE Customer.CustomerID = soh.CustomerID FOR XML AUTO, TYPE) as Orders FROM Sales.Customer as Customer ORDER BY Customer.CustomerID FOR XML AUTO, ELEMENTS; SELECT Customer.CustomerID, Customer.TerritoryID, (SELECT SalesOrderID, [Status] FROM Sales.SalesOrderHeader AS soh WHERE Customer.CustomerID = soh.CustomerID FOR XML AUTO, TYPE) as Orders FROM Sales.Customer as Customer ORDER BY Customer.CustomerID FOR XML AUTO, ELEMENTS; SELECT Cust.CustomerID, Cust.StoreID, [Order].SalesOrderID, [Order].[Status] FROM Sales.Customer AS Cust INNER JOIN Sales.SalesOrderHeader AS [Order] ON Cust.CustomerID = [Order].CustomerID ORDER BY Cust.CustomerID FOR XML AUTO, ELEMENTS; SELECT Cust.CustomerID, Cust.StoreID, [Order].SalesOrderID, [Order].[Status] FROM Sales.Customer AS Cust INNER JOIN Sales.SalesOrderHeader AS [Order] ON Cust.CustomerID = [Order].CustomerID ORDER BY Cust.CustomerID FOR XML AUTO, ELEMENTS; SELECT Cust.CustomerID, Cust.StoreID, SalesOrderID, [Status] FROM Sales.Customer AS Cust INNER JOIN Sales.SalesOrderHeader AS [Order] ON Cust.CustomerID = [Order].CustomerID ORDER BY Cust.CustomerID FOR XML AUTO; SELECT Cust.CustomerID, Cust.StoreID, SalesOrderID, [Status] FROM Sales.Customer AS Cust INNER JOIN Sales.SalesOrderHeader AS [Order] ON Cust.CustomerID = [Order].CustomerID ORDER BY Cust.CustomerID FOR XML AUTO; AUTO mode produces only attributes or elements AUTO mode produces only attributes Retrieving Nested XML Use inner FOR XML with TYPE clause to return xml data type
Demonstration 1A: FOR XML Queries In this demonstration, you will see: How to retrieve XML in RAW mode How to retrieve XML in AUTO mode How to retrieve XML in EXPLICIT mode How to retrieve XML in PATH mode How to use TYPE
Lesson 2: Getting Started with XQuery What is XQuery? query() Method value() Method exist() Method modify() Method Demonstration 2A: XQuery Methods in a DDL Trigger
What is XQuery? Can query structured or semi-structured XML FLWOR expressions StatementDescription forIterate through sibling nodes whereApply filtering criteria to the iteration order bySort values in returned resultset returnSpecify the XML to be returned Query language to identify nodes in XML
query() Method Returns untyped XML Uses an XQuery expression SELECT XmlEvent.query( ' { for $e in /EVENT_INSTANCE return {number($e/SPID[1])} } ') FROM dbo.DatabaseLog; SELECT XmlEvent.query( ' { for $e in /EVENT_INSTANCE return {number($e/SPID[1])} } ') FROM dbo.DatabaseLog;
value() Method Extracts scalar values from XML documents Returns data as a relational column SELECT CatalogDescription.value(' declare namespace PD=" dventure-works/ProductModelDescription"; ', 'int') as Result FROM Production.ProductModel WHERE CatalogDescription IS NOT NULL ORDER BY ProductModelID; SELECT CatalogDescription.value(' declare namespace PD=" dventure-works/ProductModelDescription"; ', 'int') as Result FROM Production.ProductModel WHERE CatalogDescription IS NOT NULL ORDER BY ProductModelID;
exist() Method Checks for the existence of a specific value Returns 1 when the value exists, 0 when it does not Should be used in preference to value() for better performance SELECT * FROM dbo.DatabaseLog WHERE XmlEvent.exist ('/EVENT_INSTANCE[ObjectType="TABLE"]') = 1; SELECT * FROM dbo.DatabaseLog WHERE XmlEvent.exist ('/EVENT_INSTANCE[ObjectType="TABLE"]') = 1;
'replace value of (/InvoiceList/Invoice/SalesPerson/text())[1] with "Ted"'); 'replace value of (/InvoiceList/Invoice/SalesPerson/text())[1] with "Ted"'); 'delete (/InvoiceList/Invoice/SalesPerson)[1]'); 'delete (/InvoiceList/Invoice/SalesPerson)[1]'); modify() Method 'insert element salesperson {"Bill"} as first into (/InvoiceList/Invoice)[1]'); 'insert element salesperson {"Bill"} as first into (/InvoiceList/Invoice)[1]'); “insert” adds child nodes to an XML document “replace value of” updates node in an XML document “delete” removes a node from the XML document
Demonstration 2A: XQuery Methods in a DDL Trigger In this demonstration, you will see how to use XQuery in DDL triggers
Lesson 3: Shredding XML Overview of Shredding XML data Stored Procedures for Managing In-Memory Node Trees OPENXML Working with XML Namespaces nodes() Method Demonstration 3A: Shredding XML
Overview of Shredding XML data XML document received from client 1 1 Use OPENXML to retrieve rowset 3 3 Use sp_xml_removedocument to clean up memory tree 5 5 Create internal tree representation by using sp_xml_preparedocument Create internal tree representation by using sp_xml_preparedocument 2 2 Process (or shred) the data into tables 4 4
Stored Procedures for Managing In-Memory Node Trees CREATE PROCEDURE xml AS -- Declare document handle int; -- Create memory tree EXEC -- Code for processing document goes here -- using OPENXML -- Remove memory tree EXEC CREATE PROCEDURE xml AS -- Declare document handle int; -- Create memory tree EXEC -- Code for processing document goes here -- using OPENXML -- Remove memory tree EXEC Create tree by using sp_xml_preparedocument Free memory by using sp_xml_removedocument
OPENXML <Order SalesOrderID="43860" Status="5" OrderDate=" T00:00:00"> <Order SalesOrderID="43860" Status="5" OrderDate=" T00:00:00"> SELECT * FROM OPENXML '/Customer/Order/OrderDetail', 1) WITH (CustomerID OrderID OrderDate ProdID Quantity int) SELECT * FROM OPENXML '/Customer/Order/OrderDetail', 1) WITH (CustomerID OrderID OrderDate ProdID Quantity int) From Order element From Customer element Uses attributes as default rowpattern identifies node level Defaults to Quantity attribute From OrderDetail element ColPattern identifies SalesOrderID, Status, and OrderDate
Working with XML Namespaces <Customer xmlns="urn:AW_NS" xmlns:o="urn:AW_OrderNS" CustomerID="1" CustomerType="S"> <o:Order SalesOrderID="43860" Status="5" OrderDate=" T00:00:00"> <Customer xmlns="urn:AW_NS" xmlns:o="urn:AW_OrderNS" CustomerID="1" CustomerType="S"> <o:Order SalesOrderID="43860" Status="5" OrderDate=" T00:00:00"> sp_xml_preparedocument accepts namespaces Use namespace prefix in all XPath expressions EXEC '<ROOT xmlns:rootNS="urn:AW_NS" xmlns:orderNS="urn:AW_OrderNS"/>'; SELECT * FROM OPENXML '/rootNS:Customer/orderNS:Order/orderNS:OrderDetail')... EXEC '<ROOT xmlns:rootNS="urn:AW_NS" xmlns:orderNS="urn:AW_OrderNS"/>'; SELECT * FROM OPENXML '/rootNS:Customer/orderNS:Order/orderNS:OrderDetail')...
nodes() Method SELECT 'int') Product, 'int') Qty AS nTable(nCol) SELECT 'int') Product, 'int') Qty AS nTable(nCol) SELECT EventDetail.value('PostTime[1]','datetime2') AS PostTime, EventDetail.value('SPID[1]', 'int') AS SPID, EventDetail.value('ObjectType[1]','sysname') AS ObjectType, EventDetail.value('ObjectName[1]','sysname') AS ObjectName FROM dbo.DatabaseLog AS dl CROSS APPLY dl.XmlEvent.nodes('/EVENT_INSTANCE') AS EventInfo(EventDetail) ORDER BY PostTime; SELECT EventDetail.value('PostTime[1]','datetime2') AS PostTime, EventDetail.value('SPID[1]', 'int') AS SPID, EventDetail.value('ObjectType[1]','sysname') AS ObjectType, EventDetail.value('ObjectName[1]','sysname') AS ObjectName FROM dbo.DatabaseLog AS dl CROSS APPLY dl.XmlEvent.nodes('/EVENT_INSTANCE') AS EventInfo(EventDetail) ORDER BY PostTime; Shreds XML variables into relational data Requires the APPLY operator with XML columns
Demonstration 3A: Shredding XML In this demonstration, you will see how to shred XML data using the nodes() method
Lab 18: Querying XML Data in SQL Server Exercise 1: Learn to query SQL Server data as XML Exercise 2: Write a stored procedure returning XML Challenge Exercise 3: Write a stored procedure that updates using XML (Only if time permits) Logon information Estimated time: 45 minutes
Lab Scenario In this lab, you will investigate several ways in which XML data can be used in SQL Server. You will query relational data and return it as XML and also process existing XML data using T-SQL. If you have time, your manager has an additional task for you. A new web service is being added to the marketing system. You need to create a stored procedure that will query data from a table and return it as an XML value.
Lab Review XML data could be passed to a stored procedure using either the XML data type or the nvarchar data type. What advantage does the XML data type provide over the nvarchar data type for this purpose? Which XML query mode did you use for implementing the WebStock.GetAvailableModelsAsXML stored procedure?
Module Review and Takeaways Review Questions Best Practices