LISTING 47.1 ASELECT Statement That Uses FOR XML RAW with No Additional Modifiers SELECT Name, ListPrice, Color FROM Production.Product [Product] WHERE Name LIKE ‘%Chain%’ ORDER BY Name
Trang 1CHAPTER 46 SQLCLR: Developing SQL Server Objects in NET
ORDER BY assembly_id desc
go
name assembly_id permission_set
-SQLCLR 65719 UNSAFE_ACCESS
System.Configuration.Install 65705 UNSAFE_ACCESS
System.ServiceProcess 65704 UNSAFE_ACCESS
System.Web.RegularExpressions 65703 UNSAFE_ACCESS
System.Drawing.Design 65702 UNSAFE_ACCESS
Now that you have the assembly_idfor your SQLCLR project (yours will not be the same
value as shown here), you can look up its routines and classes in sys.assembly_modules:
SELECT TOP 5
name,
assembly_class as class,
assembly_method as method
FROM sys.assembly_modules am
JOIN sys.assemblies a
ON am.assembly_id = a.assembly_id
WHERE a.assembly_id = 65719
GO
name class method
-SQLCLR StoredProcedures GetSetIllustrationWebLinks
SQLCLR StoredProcedures SpTrans
SQLCLR RegexLibrary MatchAll
SQLCLR XSLT XSLTransform
SQLCLR SumPrime NULL
Notice that the class holding your UDA (SumPrime) is listed, but your UDA itself is not
listed In addition, your UDT (RegexPattern) is not listed To see everything, you
right-click SQLCLR in the Assembliesnode of the Object Browser and then select View
Dependencies
Summary
This chapter covered the development of SQLCLR code using user-defined managed
data-base objects in conjunction with ADO.NET We also reviewed advanced topics, such as
transaction control and system catalog viewing
If you attempted the examples from start to finish, you have upgraded your SQL Server
and NET programming arsenal and opened the doorway to a new world of
data-inte-grated software
In Chapter 47, “Using XML in SQL Server 2008,” we cover SQL Server’s extensive
support for XML
Trang 2Using XML in SQL
Server 2008
What’s New in Using XML in SQL Server 2008
Understanding XML
Relational Data as XML: The
FOR XML Modes
XML as Relational Data: Using
OPENXML
Using the xml Data Type
Indexing and Full-Text Indexing
ofxml Columns
SQL Server first planted its Extensible Markup Language
(XML) roots with the introduction of the FOR XMLand
OPENXMLkeywords in SQL Server 2000, right around the
time XML was growing in popularity as a markup format
with seemingly unlimited uses
With the release of SQL Server 2008, the bar has clearly
been raised for XML support in relational databases
What’s New in Using XML in SQL
Server 2008
XML and relational data may exist side by side and are
more interchangeable than ever, thanks to SQL Server’s
XML-centric features, such as the xmldata type, extensions
toFOR XML, schema storage, content validation, indexing,
XQuery support, and more
With the release of SQL Server 2008, the SQL Server team
added support for the few XML features that were
unavail-able in SQL Server 2005, including
Support for lax validation in XML schemas
Improved support for union and list types in XML
schemas
Addition of the letclause in XQuery
Enhancements to XML Data Modification Language
(DML) expressions
The introduction of these features is both vital and timely
because XML has become the standard for everything from
Trang 3CHAPTER 47 Using XML in SQL Server 2008
traditional markup for publications to business-to-business data exchange, web services,
application programming (with XAML), graphics display (with SVG), news syndication
(with RSS), and the list goes on
But before digging into the world of SQL Server XML, let’s briefly look at what XML is
Understanding XML
XML was first created as a solution to the complexity inherent in the Standard
Generalized Markup Language (SGML), the granddaddy of all structured markup
languages What you may not know is that SGML actually contains the rules that define
how to produce other markup languages, such as HTML XML is just a subset or restriction
of those rules, providing the specifications for producing markup for all kinds of content
based on a few simple conventions
XML documents are either well formed, meaning they contain a single root element that
contains every other element (or none), or valid, meaning they are well formed and all
their elements adhere to all the constraints set forth in their associated Document Type
Definition (DTD) or XML Schema Definition (XSD)
An XML document that adheres to the constraints of a particular DTD or schema is
known as an instance of that DTD or schema In some cases, an XML document is referred
to as a fragment, meaning it contains more than one root element and/or text-only nodes.
XML documents are generally made up of elements (also called tags), attributes,
instruc-tions to the applicainstruc-tions that use the document (known as processing instrucinstruc-tions),
comments, and text Despite their variation in kind, all these structures are commonly
known as nodes.
Keep in mind that there is no set list of predefined XML tags: they can be anything the
XML specialist chooses And just as HTML is considered to be an instance of SGML, the
XML content model is also itself an instance of XML
XML’s only job is to provide the specification for how a document may be structured (or
marked up) It contains no inherent information pertaining to data display or layout,
content usage, or anything else
The pages that follow provide many examples of XML, both simple and complex We tour
the many ways SQL Server can produce, store, load, and transform XML
One of the most important uses of XML is to provide a way of describing and
encapsulat-ing relational data Doencapsulat-ing so requires a mappencapsulat-ing between two basic kinds of data
struc-tures: sets and trees The techniques shown in this section thus have a single goal:
converting the columns and rows that make up the sets derived from any SELECT
state-ment into XML trees
Trang 4Note that before XML came along, selected result sets would most likely be exported to
delimited text files for consumption by disparate systems Today, most data interchange
favors the use of XML In response, developers have come to rely on XSL for
Transformations (XSLT) as a companion skill for translating XML into HTML, PDF, RTF, or
any other type of document
Let’s look at how the SELECT FOR XMLsyntax can automatically mark up relational data
in a variety of ways The simplest approach uses FOR XML RAW
RAW Mode
When specified at the end of a SELECTstatement, the keywords FOR XML RAWtell SQL
Server to generate a one-XML-element-per-row structure The FOR XMLstatement has a few
options that change its output from the default of document fragments to well-formed
documents with a slightly (compared to a few other FOR XMLoptions) reshaped structure
This is its syntax:
FOR XML RAW [ (’ElementName’) ]
[
[ , BINARY BASE64 ]
[ , TYPE ]
[ , ROOT [ (’RootName’) ]
]
[ , { XMLDATA | XMLSCHEMA [ (’TargetNameSpaceURI’) ]} ]
[ , ELEMENTS [ XSINIL | ABSENT ] ]
Listing 47.1 illustrates the XML generated by the no-option version of FOR XML RAW (Note
that all the code in this chapter relies on the AdventureWorks2008sample database.)
LISTING 47.1 ASELECT Statement That Uses FOR XML RAW with No Additional Modifiers
SELECT Name, ListPrice, Color
FROM Production.Product [Product]
WHERE Name LIKE ‘%Chain%’
ORDER BY Name
FOR XML RAW
go
<row Name=”Chain” ListPrice=”20.2400” Color=”Silver” />
<row Name=”Chain Stays” ListPrice=”0.0000” />
<row Name=”Chainring” ListPrice=”0.0000” Color=”Black” />
<row Name=”Chainring Bolts” ListPrice=”0.0000” Color=”Silver” />
<row Name=”Chainring Nut” ListPrice=”0.0000” Color=”Silver” />
This kind of XML shape is known as attribute-centric XML because each column in the
result set is mapped to an attribute rather than an element Each row is mapped to an
element named row, which holds these attributes
Trang 5CHAPTER 47 Using XML in SQL Server 2008
Listing 47.2 illustrates how the resultant XML can be changed into an element-centric
shape, where each selected column is converted to an XML element simply through the
addition of the ELEMENTSkeyword to FOR XML RAW
LISTING 47.2 ASELECT Statement That Uses FOR XML RAW, ELEMENTS
SELECT Name, ListPrice, Color
FROM Production.Product [Product]
WHERE Name LIKE ‘%Chain%’
ORDER BY Name
FOR XML RAW, ELEMENTS
go
<row>
<Name>Chain</Name>
<ListPrice>20.2400</ListPrice>
<Color>Silver</Color>
</row>
<row>
<Name>Chain Stays</Name>
<ListPrice>0.0000</ListPrice>
</row>
<row>
<Name>Chainring</Name>
<ListPrice>0.0000</ListPrice>
<Color>Black</Color>
</row>
<row>
<Name>Chainring Bolts</Name>
<ListPrice>0.0000</ListPrice>
<Color>Silver</Color>
</row>
<row>
<Name>Chainring Nut</Name>
<ListPrice>0.0000</ListPrice>
<Color>Silver</Color>
</row>
If the tag name rowis undesirable, you can change the element name by simply adding a
string-valued parameter, in parentheses, to the RAWkeyword
Note that in contrast to FOR XML AUTO(discussed later in this chapter), in this case,
alias-ing the Production.Producttable has no effect on the output Here’s an example:
SELECT Name, ListPrice, Color
FROM Production.Product [Product]
WHERE Name LIKE ‘%Chain%’
Trang 6ORDER BY Name
FOR XML RAW(‘ChainElement’), ELEMENTS
SQL Server 2008 also enables you to return NULLcolumn values in generated XML
Previously, when a NULLcolumn value was returned in the result set when using FOR XML,
the null value was simply omitted from the XML: no attribute or element was generated
at all In SQL Server 2008, by specifying the keyword XSINILafterELEMENTS, you can
ensure that all null values are represented in the XML
Note how the xsi:nil=”true”attribute is produced for elements representing null
column values In addition, SQL Server automatically adds the XML schema namespace
declaration to each node of the resulting fragment This is required under the rules of
XML because this fragment uses a Boolean attribute called nil, which is declared in the
XML schema located at the specified URL This, as well as the effect of the ELEMENTS
keyword, is illustrated in Listing 47.3
LISTING 47.3 ASELECT Statement That Uses FOR XML RAW, ELEMENTS XSINIL
SELECT TOP 1 Name, ListPrice, Color, Weight
FROM Production.Product [Product]
WHERE Name LIKE ‘%Chain%’
ORDER BY Name
FOR XML RAW(‘ChainElement’), ELEMENTS XSINIL
go
<ChainElement xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”>
<Name>Chain</Name>
<ListPrice>20.2400</ListPrice>
<Color>Silver</Color>
<Weight xsi:nil=”true”/>
</ChainElement>
Note that the XML results in Listing 47.3 happen to produce a well-formed XML
docu-ment only because a single row was selected: this one row acts as both the root of the
document and its entire content All other XML results (including all the previous listings)
encapsulating two or more rows are actually just fragments
To easily change these XML fragments to well-formed documents, you can apply the ROOT
keyword to add a root node to the output, as shown in Listing 47.4
LISTING 47.4 ASELECT Statement That Uses FOR XML RAW and the ROOT Keyword
SELECT Name, ListPrice, Color, Weight
FROM Production.Product [Product]
WHERE Name LIKE ‘%Chain%’
ORDER BY Name
FOR XML RAW(‘ChainElement’), ELEMENTS XSINIL, ROOT(‘ChainDoc’)
go
Trang 7CHAPTER 47 Using XML in SQL Server 2008
<ChainDoc xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”>
<ChainElement>
<Name>Chain</Name>
<ListPrice>20.2400</ListPrice>
<Color>Silver</Color>
<Weight xsi:nil=”true” />
</ChainElement>
<ChainElement>
<Name>Chain Stays</Name>
<ListPrice>0.0000</ListPrice>
<Color xsi:nil=”true” />
<Weight xsi:nil=”true” />
</ChainElement>
<ChainElement>
<Name>Chainring</Name>
<ListPrice>0.0000</ListPrice>
<Color>Black</Color>
<Weight xsi:nil=”true” />
</ChainElement>
<ChainElement>
<Name>Chainring Bolts</Name>
<ListPrice>0.0000</ListPrice>
<Color>Silver</Color>
<Weight xsi:nil=”true” />
</ChainElement>
<ChainElement>
<Name>Chainring Nut</Name>
<ListPrice>0.0000</ListPrice>
<Color>Silver</Color>
<Weight xsi:nil=”true” />
</ChainElement>
</ChainDoc>
Users (or applications) on the receiving side of RAW-produced XML may also require an
inline XML schema (XSD) or an inline XML-Data Reduced (XDR) schema Note that inline
XDR schemas are considered to be deprecated in this release
To produce these schemas, you add the XMLSCHEMAorXMLDATAkeyword to the clause The
results are too long to be listed here, but to see how these schema types differ, compare
the output of this:
SELECT Name, ListPrice, Color, Weight
FROM Production.Product [Product]
WHERE Name LIKE ‘%Chain%’
ORDER BY Name
FOR XML RAW, ELEMENTS XSINIL, XMLDATA
Trang 8to the output of this:
SELECT Name, ListPrice, Color, Weight
FROM Production.Product [Product]
WHERE Name LIKE ‘%Chain%’
ORDER BY Name
FOR XML RAW(‘ChainElement’),
ELEMENTS XSINIL,
ROOT(‘ChainDoc’),
XMLSCHEMA (‘urn:www-samspublishing-com:examples’)
XML schemas are discussed in further detail later in this chapter, in the section “Using
XML Schema Collections.”
NOTE
TheXMLDATAkeyword is not permitted when ROOTis specified or when a tag name
parameter has been passed to RAW(for example,RAW(‘ChainElement’))
Note also that XMLSCHEMAtakes an optional string-valued parameter, allowing you to
specify a value for the target namespace of the produced XML (for example,XMLSCHEMA
(‘urn:www-samspublishing-com:examples))
Working with Binary Columns
Even though XML is purely a text-based markup language, FOR XMLstill has the capability
to generate XML that contains data selected from binary–data-typed columns, such as
image,binary, and varbinary To do this, SQL Server base-64 encodes the data, resulting
in a long character string
To implement this in a query, you add joins from the table Production.Productto
Production.ProductProductPhotoand then to Production.ProductPhoto, which contains
thevarbinary(max)–data-typedThumbNailPhotocolumn Then you add the keywords
BINARY BASE64to the FOR XMLclause Listing 47.5 illustrates this and also shows the
schema generated by the XMLSCHEMAkeyword (Note that the base-64 character data is
truncated in the listing for brevity with the character string { }.)
LISTING 47.5 ASELECT Statement That Uses FOR XML RAW and the BINARY BASE64
Option
SELECT TOP 1 Name, ListPrice, Color, Weight, ThumbNailPhoto
FROM Production.Product [Product]
JOIN Production.ProductProductPhoto PhotoJunction ON
[Product].ProductId = PhotoJunction.ProductId
JOIN Production.ProductPhoto Photo
ON Photo.ProductPhotoId = PhotoJunction.ProductPhotoId
WHERE Name LIKE ‘%Chain%’
ORDER BY Name
FOR XML RAW(‘ChainElement’),
Trang 9CHAPTER 47 Using XML in SQL Server 2008
ELEMENTS XSINIL,
ROOT(‘ChainDoc’),
XMLSCHEMA(‘urn:www-samspublishing-com:examples’),
BINARY BASE64
go
<ChainDoc xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”>
<xsd:schema targetNamespace=”urn:www-samspublishing-com:examples”
xmlns:xsd=”http://www.w3.org/2001/XMLSchema”
xmlns:sqltypes=”http://schemas.microsoft.com/sqlserver/2004/sqltypes”
elementFormDefault=”qualified”>
<xsd:import
namespace=http://schemas.microsoft.com/sqlserver/2004/sqltypes
schemaLocation=”http://schemas.microsoft.com/sqlserver/2004/
sqltypes/sqltypes.xsd”
/>
<xsd:element name=”ChainElement”>
<xsd:complexType>
<xsd:sequence>
<xsd:element name=”Name” nillable=”1”>
<xsd:simpleType
sqltypes:sqlTypeAlias=”[AdventureWorks2008].[dbo].[Name]”>
<xsd:restriction base=”sqltypes:nvarchar” sqltypes:localeId=”1033”
sqltypes:sqlCompareOptions=”IgnoreCase IgnoreKanaType IgnoreWidth” sqltypes:sqlSortId=”52”>
<xsd:maxLength value=”50” />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name=”ListPrice” type=”sqltypes:money” nillable=”1” />
<xsd:element name=”Color” nillable=”1”>
<xsd:simpleType>
<xsd:restriction base=”sqltypes:nvarchar” sqltypes:localeId=”1033”
sqltypes:sqlCompareOptions=”IgnoreCase IgnoreKanaType IgnoreWidth” sqltypes:sqlSortId=”52”>
<xsd:maxLength value=”15” />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name=”Weight” nillable=”1”>
<xsd:simpleType>
<xsd:restriction base=”sqltypes:decimal”>
<xsd:totalDigits value=”8” />
<xsd:fractionDigits value=”2” />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
Trang 10<xsd:element
name=”ThumbNailPhoto” type=”sqltypes:varbinary” nillable=”1”/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<ChainElement xmlns=”urn:www-samspublishing-com:examples”>
<Name>Chain</Name>
<ListPrice>20.2400</ListPrice>
<Color>Silver</Color>
<Weight xsi:nil=”true” />
<ThumbNailPhoto>R0lGODlhUAAxAPcAAKeamoyLj { }</ThumbNailPhoto>
</ChainElement>
</ChainDoc>
AUTO Mode
WhenRAWmode is not enough, FOR XML AUTOprovides a few more ways to shape your
XML output Its usefulness derives from its capability to produce nested XML elements
from rows derived by joining multiple tables, in contrast to the flat structure of RAWmode
TheROOTkeyword introduced earlier also applies with AUTOmode, and it is good practice
to continue to use it in your queries Like RAWmode,AUTOmode produces attribute-centric
XML by default, but you can change this by using the ELEMENTSkeyword.XSINILand
XMLSCHEMAare also applicable here, having the same effect as with RAWmode Listing 47.6
illustrates these points
LISTING 47.6 ASELECT Statement That Uses FOR XML AUTO, ELEMENTS XSINIL,
ROOT
SELECT
Color,
Offer.SpecialOfferId Id,
Product.ProductId Id,
Name,
Description [Desc],
Size
FROM Sales.SpecialOffer Offer
JOIN Sales.SpecialOfferProduct OP ON
OP.SpecialOfferId = Offer.SpecialOfferId
JOIN Production.Product Product ON
Product.ProductId = OP.ProductId
WHERE Name LIKE ‘Mountain Bike%’
FOR XML AUTO, ELEMENTS XSINIL, ROOT(‘MountainBikeSpecials’)
go