Subscribe To

Subscribe to SQL Server and XML by Email
Labels

Sunday, October 26, 2008

SQL Server XML Tutorials - XQuery Tutorial 21

This series of posts is part of the SQL Server XML Tutorials series that presents a set of XQuery, XSD, FOR XML and XML Bulk Load tutorials. This series of tutorials present several dozen representation/structure of an Order Information XML document and explains how to process them using XQuery and XML Bulk Load component. Then it explains how to create an XSD schema for the given XML document. It also explains how to generate such a document using FOR XML directive.

Each XQuery tutorial in this series will present 3 different versions of the XQuery example:

  1. Reading information from an XML variable
  2. Reading information from an XML Column
  3. Reading information from an XML file

This tutorial demonstrates how to read information from an XML document using XQuery. We will use Sample XML Document 21 for the example in this post. Here is a list of all the different XML documents we will use throughout this series of tutorials.

This example is slightly different from the other examples we saw previously. The major difference is that, all the sample documents we saw previously had information of only one order. This example shows how to process the data if we have more than one order information in the XML document. One significant change added to the code is an extra CROSS APPLY that joins the details part with the header node, so that we can retrieve the order number along with item details. For example:

SELECT 
    o.value('@Number','VARCHAR(10)') AS OrderNumber,
    i.value('@ItemNumber','VARCHAR(10)') AS ItemNumber,
    i.value('@Quantity','INT') AS Quantity,
    i.value('@Price','MONEY') AS Price
FROM @x.nodes('/Orders/Order') ord(o)
CROSS APPLY o.nodes('Items/Item') itm(i)
/*
OrderNumber ItemNumber Quantity    Price
----------- ---------- ----------- ---------------------
20001       FB001923   12          18.25
20001       SG060020   80          12.75
20001       FB019090   24          6.00
20002       FB001923   5           18.25
20002       SG060020   25          12.75
20002       FB019090   15          6.00
*/

Note that the above code retrieves order number from the order header node and order details from the detail node. The nodes are linked using a CROSS apply. Let us now see the complete source code listing.

Reading information from an XML variable

-- ------------------------------------------------------------------
-- Declare an XML variable and assign value
-- ------------------------------------------------------------------
DECLARE @x XML
SELECT @x = '
<Orders>
  <Order Number="20001" Date="2008-01-01Z">
    <DeliveryDate>2008-01-20T08:00:00-08:00</DeliveryDate>
    <Customer Number="GREAL">
      <Name>Great Lakes Food Market</Name>
      <Billing City="Eugene" State="OR" Zip="97403">
        <Address>2732 Baker Blvd.</Address>
      </Billing>
      <Shipping City="Eugene" State="OR" Zip="97403">
        <Address>2732 Baker Blvd.</Address>
      </Shipping>
      <Terms>30 Days Credit</Terms>
      <Contact Name="Howard Snyder" Title="Purchase Manager">
        <Email>hsnyder@greatlakes.com</Email>
        <Phone>(503) 555-7555</Phone>
        <Fax>(503) 555-2376</Fax>
      </Contact>
    </Customer>
    <Items>
      <Item ItemNumber="FB001923" Quantity="12" Price="18.25" />
      <Item ItemNumber="SG060020" Quantity="80" Price="12.75" />
      <Item ItemNumber="FB019090" Quantity="24" Price="6.00" />
    </Items>
    <OrderNote>Delivery needed before 8 AM</OrderNote>
    <InvoiceNote>
      Adjust the previous credit note with this invoice
    </InvoiceNote>
    <DiscountAmount>300</DiscountAmount>
  </Order>
  <Order Number="20002" Date="2008-01-02Z">
    <DeliveryDate>2008-01-21T08:00:00-08:00</DeliveryDate>
    <Customer Number="GREAL">
      <Name>Great Lakes Food Market</Name>
      <Billing City="Eugene" State="OR" Zip="97403">
        <Address>2732 Baker Blvd.</Address>
      </Billing>
      <Shipping City="Eugene" State="OR" Zip="97403">
        <Address>2732 Baker Blvd.</Address>
      </Shipping>
      <Terms>30 Days Credit</Terms>
      <Contact Name="Howard Snyder" Title="Purchase Manager">
        <Email>hsnyder@greatlakes.com</Email>
        <Phone>(503) 555-7555</Phone>
        <Fax>(503) 555-2376</Fax>
      </Contact>
    </Customer>
    <Items>
      <Item ItemNumber="FB001923" Quantity="5" Price="18.25" />
      <Item ItemNumber="SG060020" Quantity="25" Price="12.75" />
      <Item ItemNumber="FB019090" Quantity="15" Price="6.00" />
    </Items>
    <OrderNote>Delivery needed before 8 AM</OrderNote>
    <InvoiceNote>
      Adjust the previous credit note with this invoice
    </InvoiceNote>
    <DiscountAmount>300</DiscountAmount>
  </Order>
</Orders>'

-- ------------------------------------------------------------------
-- Read Order Header Information
-- ------------------------------------------------------------------
SELECT
    x.value('@Number[1]','VARCHAR(20)') AS OrderNumber,
    x.value('xs:date(@Date[1])','DATETIME') AS OrderDate,
    x.value('DeliveryDate[1] cast as xs:dateTime ?','DATETIME') 
        AS DeliveryDate,
    x.value('(Customer/@Number)[1]','VARCHAR(20)') AS CustomerNumber,
    x.value('(Customer/Name)[1]','VARCHAR(40)') AS CustomerName,
    x.value('(Customer/Billing/@City)[1]','VARCHAR(20)') AS BillingCity,
    x.value('(Customer/Billing/@State)[1]','VARCHAR(10)') AS BillingState,
    x.value('(Customer/Billing/@Zip)[1]','VARCHAR(5)') AS BillingZip,
    x.value('(Customer/Billing/Address)[1]','VARCHAR(50)') AS BillingAddress,
    x.value('(Customer/Shipping/@City)[1]','VARCHAR(20)') AS ShippingCity,
    x.value('(Customer/Shipping/@State)[1]','VARCHAR(10)') AS ShippingState,
    x.value('(Customer/Shipping/@Zip)[1]','VARCHAR(5)') AS ShippingZip,
    x.value('(Customer/Shipping/Address)[1]','VARCHAR(50)') AS ShippingAddress,
    x.value('(Customer/Terms)[1]','VARCHAR(50)') AS Terms,
    x.value('(Customer/Contact/@Name)[1]','VARCHAR(40)') AS ContactName,
    x.value('(Customer/Contact/@Title)[1]','VARCHAR(40)') AS ContactTitle,
    x.value('(Customer/Contact/Email)[1]','VARCHAR(50)') AS ContactEmail,
    x.value('(Customer/Contact/Phone)[1]','VARCHAR(20)') AS ContactPhone,
    x.value('(Customer/Contact/Fax)[1]','VARCHAR(20)') AS ContactFax,
    x.value('OrderNote[1]','VARCHAR(50)') AS OrderNote,
    x.value('InvoiceNote[1]','VARCHAR(50)') AS InvoiceNote,
    x.value('DiscountAmount[1]','MONEY') AS DiscountAmount
FROM @x.nodes('Orders/Order') ord(x)

-- ------------------------------------------------------------------
-- Read Item details
-- ------------------------------------------------------------------
SELECT 
    o.value('@Number','VARCHAR(10)') AS OrderNumber,
    i.value('@ItemNumber','VARCHAR(10)') AS ItemNumber,
    i.value('@Quantity','INT') AS Quantity,
    i.value('@Price','MONEY') AS Price
FROM @x.nodes('/Orders/Order') ord(o)
CROSS APPLY o.nodes('Items/Item') itm(i)

Reading information from an XML column

-- ------------------------------------------------------------------
-- Create a table and insert an XML value into an XML column
-- ------------------------------------------------------------------
DECLARE @t TABLE (OrderInfo XML)
INSERT INTO @t (OrderInfo) SELECT '
<Orders>
  <Order Number="20001" Date="2008-01-01Z">
    <DeliveryDate>2008-01-20T08:00:00-08:00</DeliveryDate>
    <Customer Number="GREAL">
      <Name>Great Lakes Food Market</Name>
      <Billing City="Eugene" State="OR" Zip="97403">
        <Address>2732 Baker Blvd.</Address>
      </Billing>
      <Shipping City="Eugene" State="OR" Zip="97403">
        <Address>2732 Baker Blvd.</Address>
      </Shipping>
      <Terms>30 Days Credit</Terms>
      <Contact Name="Howard Snyder" Title="Purchase Manager">
        <Email>hsnyder@greatlakes.com</Email>
        <Phone>(503) 555-7555</Phone>
        <Fax>(503) 555-2376</Fax>
      </Contact>
    </Customer>
    <Items>
      <Item ItemNumber="FB001923" Quantity="12" Price="18.25" />
      <Item ItemNumber="SG060020" Quantity="80" Price="12.75" />
      <Item ItemNumber="FB019090" Quantity="24" Price="6.00" />
    </Items>
    <OrderNote>Delivery needed before 8 AM</OrderNote>
    <InvoiceNote>
      Adjust the previous credit note with this invoice
    </InvoiceNote>
    <DiscountAmount>300</DiscountAmount>
  </Order>
  <Order Number="20002" Date="2008-01-02Z">
    <DeliveryDate>2008-01-21T08:00:00-08:00</DeliveryDate>
    <Customer Number="GREAL">
      <Name>Great Lakes Food Market</Name>
      <Billing City="Eugene" State="OR" Zip="97403">
        <Address>2732 Baker Blvd.</Address>
      </Billing>
      <Shipping City="Eugene" State="OR" Zip="97403">
        <Address>2732 Baker Blvd.</Address>
      </Shipping>
      <Terms>30 Days Credit</Terms>
      <Contact Name="Howard Snyder" Title="Purchase Manager">
        <Email>hsnyder@greatlakes.com</Email>
        <Phone>(503) 555-7555</Phone>
        <Fax>(503) 555-2376</Fax>
      </Contact>
    </Customer>
    <Items>
      <Item ItemNumber="FB001923" Quantity="5" Price="18.25" />
      <Item ItemNumber="SG060020" Quantity="25" Price="12.75" />
      <Item ItemNumber="FB019090" Quantity="15" Price="6.00" />
    </Items>
    <OrderNote>Delivery needed before 8 AM</OrderNote>
    <InvoiceNote>
      Adjust the previous credit note with this invoice
    </InvoiceNote>
    <DiscountAmount>300</DiscountAmount>
  </Order>
</Orders>'

-- ------------------------------------------------------------------
-- Read Order Header Information
-- ------------------------------------------------------------------
SELECT
    x.value('@Number[1]','VARCHAR(20)') AS OrderNumber,
    x.value('xs:date(@Date[1])','DATETIME') AS OrderDate,
    x.value('DeliveryDate[1] cast as xs:dateTime ?','DATETIME') 
        AS DeliveryDate,
    x.value('(Customer/@Number)[1]','VARCHAR(20)') AS CustomerNumber,
    x.value('(Customer/Name)[1]','VARCHAR(40)') AS CustomerName,
    x.value('(Customer/Billing/@City)[1]','VARCHAR(20)') AS BillingCity,
    x.value('(Customer/Billing/@State)[1]','VARCHAR(10)') AS BillingState,
    x.value('(Customer/Billing/@Zip)[1]','VARCHAR(5)') AS BillingZip,
    x.value('(Customer/Billing/Address)[1]','VARCHAR(50)') AS BillingAddress,
    x.value('(Customer/Shipping/@City)[1]','VARCHAR(20)') AS ShippingCity,
    x.value('(Customer/Shipping/@State)[1]','VARCHAR(10)') AS ShippingState,
    x.value('(Customer/Shipping/@Zip)[1]','VARCHAR(5)') AS ShippingZip,
    x.value('(Customer/Shipping/Address)[1]','VARCHAR(50)') AS ShippingAddress,
    x.value('(Customer/Terms)[1]','VARCHAR(50)') AS Terms,
    x.value('(Customer/Contact/@Name)[1]','VARCHAR(40)') AS ContactName,
    x.value('(Customer/Contact/@Title)[1]','VARCHAR(40)') AS ContactTitle,
    x.value('(Customer/Contact/Email)[1]','VARCHAR(50)') AS ContactEmail,
    x.value('(Customer/Contact/Phone)[1]','VARCHAR(20)') AS ContactPhone,
    x.value('(Customer/Contact/Fax)[1]','VARCHAR(20)') AS ContactFax,
    x.value('OrderNote[1]','VARCHAR(50)') AS OrderNote,
    x.value('InvoiceNote[1]','VARCHAR(50)') AS InvoiceNote,
    x.value('DiscountAmount[1]','MONEY') AS DiscountAmount
FROM @t
CROSS APPLY OrderInfo.nodes('Orders/Order') ord(x)

-- ------------------------------------------------------------------
-- Read Item details
-- ------------------------------------------------------------------
SELECT 
    o.value('@Number','VARCHAR(10)') AS OrderNumber,
    i.value('@ItemNumber','VARCHAR(50)') AS ItemNumber,
    i.value('@Quantity','INT') AS Quantity,
    i.value('@Price','MONEY') AS Price
FROM @t
CROSS APPLY OrderInfo.nodes('/Orders/Order') ord(o)
CROSS APPLY o.nodes('Items/Item') itm(i)

Reading information from an XML file

-- ------------------------------------------------------------------
-- Declare an XML variable and load information from an XML File
-- ------------------------------------------------------------------
DECLARE @x XML
SELECT @x = CONVERT(XML, bulkcolumn, 2) 
FROM OPENROWSET(BULK 'C:\temp\order21.xml', SINGLE_BLOB) AS x

-- ------------------------------------------------------------------
-- Read Order Header Information
-- ------------------------------------------------------------------
SELECT
    x.value('@Number[1]','VARCHAR(20)') AS OrderNumber,
    x.value('xs:date(@Date[1])','DATETIME') AS OrderDate,
    x.value('DeliveryDate[1] cast as xs:dateTime ?','DATETIME') 
        AS DeliveryDate,
    x.value('(Customer/@Number)[1]','VARCHAR(20)') AS CustomerNumber,
    x.value('(Customer/Name)[1]','VARCHAR(40)') AS CustomerName,
    x.value('(Customer/Billing/@City)[1]','VARCHAR(20)') AS BillingCity,
    x.value('(Customer/Billing/@State)[1]','VARCHAR(10)') AS BillingState,
    x.value('(Customer/Billing/@Zip)[1]','VARCHAR(5)') AS BillingZip,
    x.value('(Customer/Billing/Address)[1]','VARCHAR(50)') AS BillingAddress,
    x.value('(Customer/Shipping/@City)[1]','VARCHAR(20)') AS ShippingCity,
    x.value('(Customer/Shipping/@State)[1]','VARCHAR(10)') AS ShippingState,
    x.value('(Customer/Shipping/@Zip)[1]','VARCHAR(5)') AS ShippingZip,
    x.value('(Customer/Shipping/Address)[1]','VARCHAR(50)') AS ShippingAddress,
    x.value('(Customer/Terms)[1]','VARCHAR(50)') AS Terms,
    x.value('(Customer/Contact/@Name)[1]','VARCHAR(40)') AS ContactName,
    x.value('(Customer/Contact/@Title)[1]','VARCHAR(40)') AS ContactTitle,
    x.value('(Customer/Contact/Email)[1]','VARCHAR(50)') AS ContactEmail,
    x.value('(Customer/Contact/Phone)[1]','VARCHAR(20)') AS ContactPhone,
    x.value('(Customer/Contact/Fax)[1]','VARCHAR(20)') AS ContactFax,
    x.value('OrderNote[1]','VARCHAR(50)') AS OrderNote,
    x.value('InvoiceNote[1]','VARCHAR(50)') AS InvoiceNote,
    x.value('DiscountAmount[1]','MONEY') AS DiscountAmount
FROM @x.nodes('Orders/Order') ord(x)

-- ------------------------------------------------------------------
-- Read Item details
-- ------------------------------------------------------------------
SELECT 
    o.value('@Number','VARCHAR(10)') AS OrderNumber,
    i.value('@ItemNumber','VARCHAR(50)') AS ItemNumber,
    i.value('@Quantity','INT') AS Quantity,
    i.value('@Price','MONEY') AS Price
    FROM @x.nodes('/Orders/Order') ord(o)
    CROSS APPLY o.nodes('Items/Item') itm(i)

SEE ALSO

 

0 comments:

Post a Comment

About Me
Jacob Sebastian
Tutorials
* XQuery Tutorials
My Links
SQL Server White Papers
SQL Server 2008
My Articles
XML Workshop RSS Feed
Contact me
Readers
Free Hit Counter
Web Site Hit Counters
SQL Server Bloggers
Blog Directories
blogarama - the blog directory Programming Blogs - BlogCatalog Blog Directory
 
Copyright Jacob Sebastian