*/ Thequerymethod takes an XQuery expression that can be customized to locate and retrieve specific nodes matching a given condition: SELECT ItemData.query’/Order/Item[@ItemNumber="D001"
Trang 1<Orders xmlns="http://www.sqlserverbible.com/orders">
<Order CustomerID="1">SO101</Order>
<Order CustomerID="1">SO102</Order>
</Orders>
*/
The following example demonstrates how to generate elements with multiple namespaces:
;WITH XMLNAMESPACES(
‘http://www.sqlserverbible.com/customers’ AS cust,
‘http://www.sqlserverbible.com/orders’ AS ord )
SELECT OrderNumber AS ‘ord:OrderNumber’, CustomerID AS ‘cust:CustomerID’
FROM OrderHeader WHERE OrderID = 1 FOR XML PATH(’’),ROOT(’Orders’) /*
<Orders xmlns:ord="http://www.sqlserverbible.com/orders"
xmlns:cust="http://www.sqlserverbible.com/customers">
<ord:OrderNumber>SO101</ord:OrderNumber>
<cust:CustomerID>1</cust:CustomerID>
</Orders>
*/
An element can be associated with a namespace by specifying a colonized name as the element name
(a name that contains a namespace name and element name separated by a colon)
WITH XMLNAMESPACESoffers a very easy way to generate XML output with namespace declarations
XML documents can be created with one or more namespace declarations
Understanding XQuery and FLWOR operations
XQuery is a W3C recommended language created for querying XML documents In a simplified sense,
one could say that ‘‘XQuery is to XML what SQL is to a relational database.’’
Thequery()method of theXMLdata type implements a subset of XQuery specifications and provides
a very extensive set of functionalities that enables performing a number of interesting operations on XML
documents
Simple queries
The basic usage of thequery()method is to retrieve one or more XML nodes from the given XML
document The result of thequery()method is always anXMLdata type value:
SELECT ItemData.query(’/Order/Item’) FROM OrderXML
Trang 2<Item ItemNumber="D001" Quantity="1" Price="900" />
<Item ItemNumber="Z001" Quantity="1" Price="200" />
<Item ItemNumber="D001" Quantity="1" Price="900" />
*/
Thequery()method takes an XQuery expression that can be customized to locate and retrieve specific
nodes matching a given condition:
SELECT
ItemData.query(’/Order/Item[@ItemNumber="D001"]’)
FROM OrderXML
/*
<Item ItemNumber="D001" Quantity="1" Price="900" />
<Item ItemNumber="D001" Quantity="1" Price="900" />
*/
The result of thequery()method can be used as input for other operations, such as the example
given here:
SELECT
OrderID,
ItemData.query(’
count(/Order/Item)
‘).value(’.’,’INT’) AS LineCount
FROM OrderXML
/*
OrderID LineCount
*/
This example used the XQuerycount()method to retrieve the number ofItemelements in each row
Thequery()method always returns anXMLdata type value; hence, thevalue()method is used to
retrieve anINTvalue from it
FLWOR operation
The true power of XQuery comes with theFLWORoperation, which is pronounced like ‘‘flower’’ and
stands forFOR LET WHERE ORDER BYandRETURN AFLWORoperation enables querying or
transform-ing XML documents It can be used either to extract specific information from an XML document or to
restructure the XML document and return a completely new XML value
A basicFLWORquery usingFORandRETURNis shown in the following example:
DECLARE @x XML
SELECT @x = ‘
<Items>
<ItemNumber>1003</ItemNumber>
Trang 3</Items>’
SELECT
@x.query(’
for $item in Items/ItemNumber return $item ‘)
/*
<ItemNumber>1003</ItemNumber>
<ItemNumber>1004</ItemNumber>
*/
WHEREandORDER BYcan be specified to filter and sort the output:
DECLARE @x XML SELECT @x = ‘
<Items>
<ItemNumber>1003</ItemNumber>
<ItemNumber>1004</ItemNumber>
<ItemNumber>1001</ItemNumber>
<ItemNumber>2007</ItemNumber>
<ItemNumber>3009</ItemNumber>
<ItemNumber>4005</ItemNumber>
</Items>’
SELECT
@x.query(’
for $item in Items/ItemNumber where $item[ < "2000"]
order by $item return $item ‘)
/*
<ItemNumber>1001</ItemNumber>
<ItemNumber>1003</ItemNumber>
<ItemNumber>1004</ItemNumber>
*/
TheWHEREcondition in the preceding XQuery expression filters the nodes forItemNumberless than
2000 TheORDER BYclause then orders the nodes byItemNumber
AFLWORoperation can be used to completely restructure an XML document, as demonstrated here:
DECLARE @x XML SELECT @x = ‘
<Item ItemNumber="D001" Quantity="1" Price="900" />
<Item ItemNumber="Z001" Quantity="1" Price="200" />’
Trang 4@x.query(’
for $item in Item
return
<ItemNumber>
{data($item/@ItemNumber)}
</ItemNumber> ‘) /*
<ItemNumber>D001</ItemNumber>
<ItemNumber>Z001</ItemNumber>
*/
The preceding example transforms theItemNumberattributes to elements and produces a completely
different XML document Complex FLWORoperations can be applied on an XML document to achieve
very complex transformation requirements
What’s new for XQuery in SQL Server 2008
SQL Server 2008 adds support for theletclause inFLWORoperations Theletclause allows declaring
and using inline variables within the XQuery expression used in aFLWORquery:
DECLARE @x XML
SELECT @x = ‘
<Item ItemNumber="D001" Quantity="2" Price="900" />
<Item ItemNumber="Z001" Quantity="3" Price="200" />’
SELECT
@x.query(’
for $item in Item
let $itm := $item/@ItemNumber
let $tot := $item/@Quantity * $item/@Price
return
<Item>
<ItemNumber>{data($itm)}</ItemNumber>
<TotalPrice>{data($tot)}</TotalPrice>
</Item>
‘)
/*
<Item>
<ItemNumber>D001</ItemNumber>
<TotalPrice>1800</TotalPrice>
</Item>
<Item>
<ItemNumber>Z001</ItemNumber>
<TotalPrice>600</TotalPrice>
</Item>
*/
Trang 5The XQuery expression in the preceding example declares two inline variables using theletclause:
$itmand$tot These variables are initialized within the XQuery expression and used to generate
cus-tom XML nodes
Theletclause reduces the complexity ofFLWORoperations by enabling complex expressions to be
translated into variables
Understanding XQuery Functions
The XQuery specification has defined a number of XQuery functions, many of which have been
implemented by SQL Server This section briefly examines the XQuery functions supported by SQL
Server 2008
String functions
String functions are one of the most commonly used set of functions in any language SQL Server 2008
supports the following XQuery string functions:
■ string()
■ concat()
■ substring()
■ contains()
■ string-length()
Thestring()function is a data accessor function that returns the string value from an element or
attribute Theconcat()function joins two string values, and thesubstring()function returns
a substring from a given value, starting at a specified position and having a specified length The
string-length()function returns the length of a given string value Finally, thecontains()
function accepts two string values and returns true if the second value is a substring of the first value
Numeric and aggregate functions
SQL Server 2008 supports the following XQuery aggregate functions These functions can be used to
perform aggregate operations over the nodes of an XML document:
■ min()
■ max()
■ count()
■ sum()
■ avg()
Trang 6Support for the following XQuery numeric functions is implemented in SQL Server 2008:
■ ceiling()
■ floor()
■ round()
The functionality exposed by each of these functions is self-explanatory All these functions exist in
T-SQL as well, and the T-T-SQL versions of these functions provide the same functionality as the XQuery
versions (except that the T-SQL function is applied on relational rows, whereas the XQuery version is
applied on XML nodes)
Other functions
SQL Server 2008 supports a few more XQuery functions that may be less commonly used, but are still
worth a mention here:
■ Data accessor function:data()
■ Boolean functions:not(),true(), andfalse()
■ Sequence functions:empty(),distinct-values(), andid()
■ Node functions:number(),local-name(), andnamespace-uri()
■ Context functions:last()andposition()
■ QName functions:expanded-QName(),local-name-from-QName()and
namespace-uri-from-QName
■ SQL Server XQuery extension functions:sql:variable()andsql:column()
The XQuery implementation of SQL Server 2008 still does not support user-defined functions (UDFs),
recommended by the XQuery specification Future versions of SQL Server might add support for
user-defined functions within XQuery expressions, and the addition of XQuery UDFs will provide more
programming power to the T-SQL developer
Performing XML Data Modification
Themodify()method of theXMLdata type can be used to perform DML operations on XML
docu-ments It allows performing insert, update, and delete operations on XML variables or columns
Theinsert,replace value of, anddeleteinstructions are used with themodify()method to
performINSERT,UPDATE, andDELETEoperations on XML documents Each of these operations has
its own syntax and is briefly explained in the following sections
Trang 7Insert operation
A new element or attribute can be inserted into an XML document by using themodify()method
with theinsertcommand A basic example demonstrating aninsertoperation is given here:
DECLARE @x XML SELECT @x = ‘<SalesOrder OrderNumber="SO101"/>’
DECLARE @CustomerID INT SELECT @CustomerID = 1 SET @x.modify(’
insert element CustomerID {sql:variable("@CustomerID")}
as last into (SalesOrder)[1]
‘)
SELECT @x /*
<SalesOrder OrderNumber="SO101">
<CustomerID>1</CustomerID>
</SalesOrder>
*/
Update operation
Themodify()method can be used withreplace value ofcommand to modify the value of
ele-ments or attributes The following example changes the value of theCustomerIDelement:
DECLARE @x XML SELECT @x = ‘
<SalesOrder OrderNumber="SO101">
<CustomerID>1</CustomerID>
</SalesOrder>’
DECLARE @CustomerID INT SELECT @CustomerID = 2
SET @x.modify(’
replace value of (SalesOrder/CustomerID/text())[1]
with sql:variable("@CustomerID")
‘)
SELECT @x
/*
<SalesOrder OrderNumber="SO101">
<CustomerID>1</CustomerID>
</SalesOrder>
*/
Trang 8Delete operation
Themodify()method can be used with thedeleteinstruction to remove an element or attribute
from a given XML document The following example deletes theCustomerIDelement from the XML
document:
DECLARE @x XML
SELECT @x = ‘
<SalesOrder OrderNumber="SO101">
<CustomerID>1</CustomerID>
</SalesOrder>’
SET @x.modify(’
delete (SalesOrder/CustomerID)[1]
‘)
SELECT @x
/*
<SalesOrder OrderNumber="SO101" />
*/
What’s new for XML DML operations in SQL Server 2008
SQL Server 2005’s implementation of themodify()method does not support XML variables with
theinsertinstruction With SQL Server 2005, it is not possible to insert an XML value into an
XML document A possible workaround is to cast the XML value toVARCHAR/NVARCHARand
per-form an insert operation However, in such a case, SQL Server will encode the XML tags within the
VARCHAR/NVARCHARvalue, which may not be the desired result most of the time
SQL Server 2008 enhanced themodify()method to support XML variables with theinsert
com-mand The following code snippet shows an example:
DECLARE @doc XML, @val XML
SELECT @doc = ‘
<SalesOrder OrderNumber="SO101">
<CustomerID>1</CustomerID>
</SalesOrder>’
SELECT @val = ‘
<Items>
<Item ItemNumber="Z001" Quantity="1" Price="900"/>
</Items>’
SET @doc.modify(’
insert sql:variable("@val")
as last into (SalesOrder)[1]
‘)
SELECT @doc
Trang 9<SalesOrder OrderNumber="SO101">
<CustomerID>1</CustomerID>
<Items>
<Item ItemNumber="Z001" Quantity="1" Price="900" />
</Items>
</SalesOrder>
*/
Note that the syntax of theinsertcommand is slightly different when an XML value is being inserted
Handling Namespaces
XML uses namespaces to disambiguate elements and attributes If the XML document contains
name-space declarations, then the XQuery expressions for querying or modifying the XML document should
also contain the required namespace declarations to identify and access the correct XML nodes
TheWITH NAMESPACESdirective can be used to declare the XML namespaces and refer to them in the
XQuery expressions following the declaration:
DECLARE @x XML SELECT @x = ‘
<SalesOrder xmlns="http://www.sqlserverbible.com/order"
xmlns:cust="http://www.sqlserverbible.com/customer">
<OrderID>1</OrderID>
<cust:CustomerID>10001</cust:CustomerID>
</SalesOrder>’
;WITH XMLNAMESPACES(
DEFAULT ‘http://www.sqlserverbible.com/order’,
‘http://www.sqlserverbible.com/customer’ AS cust )
SELECT
@x.value(’(SalesOrder/OrderID)[1]’,’INT’) AS OrderID,
@x.value(’(SalesOrder/cust:CustomerID)[1]’,’INT’) AS CustomerID
/*
OrderID CustomerID
*/
TheWITH XMLNAMESPACESdirective simplifies namespace declaration, as the namespaces can be
declared once and then reused in the XQuery expression that follows the declaration
Trang 10Shredding XML Using OPENXML()
OPENXML(), released along with SQL Server 2000, was the first XML shredding function added to SQL
Server.OPENXML()is very powerful and is the only option available to shred XML documents (from
T-SQL) in SQL Server 2000 SQL Server 2005 added support for XQuery, which is a better choice over
OPENXML() in most cases SQL Server 2008 enhanced the XQuery functionalities further by adding
support for ‘‘let’’ clause in FLWOR operations
The following example shows a basicOPENXML()function call:
DECLARE @hdoc INT
DECLARE @xml VARCHAR(MAX)
SET @xml =’
<SalesOrder OrderNumber="SO101">
<Items>
<Item ItemNumber="D001" Quantity="1" Price="900.0000" />
<Item ItemNumber="Z001" Quantity="1" Price="200.0000" />
</Items>
</SalesOrder>’
Step 1: initialize XML Document Handle
EXEC sp_xml_preparedocument @hdoc OUTPUT, @xml
Step 2: Call OPENXML()
SELECT * FROM OPENXML(@hdoc, ‘/SalesOrder/Items/Item’)
WITH (
OrderNumber CHAR(5) ‘ / /@OrderNumber’,
ItemNumber CHAR(4) ‘@ItemNumber’,
Quantity INT ‘@Quantity’,
Price MONEY ‘@Price’
)
Step 3: Free document handle
exec sp_xml_removedocument @hdoc
/*
OrderNumber ItemNumber Quantity Price
- - -
*/
As is apparent from the preceding example, a call toOPENXML()is always a three-step process Before
the function can be called, a document handle for the current XML document should be created and
initialized This handle should be passed to theOPENXML()function call as an argument Finally, the
handle has to be released to free system resources used for the operation