1. Trang chủ
  2. » Công Nghệ Thông Tin

Microsoft SQL Server 2008 R2 Unleashed- P192 potx

10 138 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 10
Dung lượng 200,36 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

AnnualSales=”{$N/AnnualSales}” SalesPlusRevenue=”{$Total}”/> ‘ FROM Sales.Store WHERE Demographics.exist‘//AnnualRevenue[xs:integer.=300000]’ = 1 The where Clause Just like the WHEREclau

Trang 1

for $outer in /outernode,

$inner in $outer/innernode

return

<Outside letter=”{$outer/@name}”>

<Inside number=”{$inner}”/>

</Outside>

‘)

go

<Outside letter=”a”>

<Inside number=”1” />

</Outside>

<Outside letter=”a”>

<Inside number=”2” />

</Outside>

<Outside letter=”a”>

<Inside number=”3” />

</Outside>

<Outside letter=”b”>

<Inside number=”4” />

</Outside>

<Outside letter=”b”>

<Inside number=”5” />

</Outside>

<Outside letter=”b”>

<Inside number=”6” />

</Outside>

The let Clause New to SQL Server 2008, the letclause is the L in FLWOR It performs

the critical function of enabling variable value assignments in XQuery expressions Here’s

an example:

WITH XMLNAMESPACES

(

DEFAULT

‘http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey’

)

SELECT TOP 1

Demographics.query(

for $N in /StoreSurvey

let $Total := ($N/AnnualRevenue + $N/AnnualSales)

order by $N/AnnualSales

return

<Statement

AnnualRevenue=”{$N/AnnualRevenue}”

Trang 2

AnnualSales=”{$N/AnnualSales}”

SalesPlusRevenue=”{$Total}”/>

‘)

FROM Sales.Store

WHERE Demographics.exist(‘(//AnnualRevenue[xs:integer(.)=300000])’) = 1

The where Clause Just like the WHEREclause in T-SQL, XQuery’s whereclause restricts the

nodes in the selected node list to those matching a certain expression Here’s an example:

SELECT TOP 1 Resume.query(‘

declare namespace

ns=”http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume”;

for $ResumeNode in /ns:Resume

where count($ResumeNode/ns:Employment) > 2

return

$ResumeNode/ns:Employment/ns:Emp.JobTitle

‘)

FROM HumanResources.JobCandidate

go

<ns:Emp.JobTitle

xmlns:ns=”http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume”>

Lead Machinist

</ns:Emp.JobTitle>

<ns:Emp.JobTitle

xmlns:ns=”http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume”>

Machinist

</ns:Emp.JobTitle>

<ns:Emp.JobTitle

xmlns:ns=”http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume”>

Assistant Machinist

</ns:Emp.JobTitle>

Here, you use the T-SQL-analogouscount()aggregate function to restrict the result set

tons:Resumenodes having three or morens:Employmentchildren The standard

aggre-gate functions are available in XQuery expressions They aremax(),min(),avg(),sum(),

andcount().

The order by Clause Just like T-SQL’s ORDER BY, XQuery’s order byis used to reorder

the selected nodes from the default document order to a new order, based on an

expres-sion The order may be set to descendingorascending(the default).

Trang 3

The following example casts a node value to an instance of the xs:datetype and orders

the results from most to least recent date:

SELECT Resume.query(‘

declare namespace

ns=”http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume”;

<Achievements>

{

for $EducationNode in //ns:Education

order by xs:date(string($EducationNode/ns:Edu.EndDate[1])) descending

return

<Degree>

<DateAwarded>

{ string($EducationNode/ns:Edu.EndDate[1]) }

</DateAwarded>

<Name>

{ string($EducationNode/ns:Edu.Degree[1]) }

</Name>

</Degree>

}

</Achievements>

‘)

FROM HumanResources.JobCandidate

WHERE JobCandidateId = 2

go

<Achievements>

<Degree>

<DateAwarded>1997-06-03Z</DateAwarded>

<Name>Bachelor of Science</Name>

</Degree>

<Degree>

<DateAwarded>1993-06-12Z</DateAwarded>

<Name>Diploma</Name>

</Degree>

</Achievements>

The expression xs:date(string($EducationNode/ns:Edu.EndDate[1]))requires some

explanation Working from the inside out: ns:Edu.EndDateis selected, using the child

node of the node stored in the bound context variable $EducationNode For the string()

typecasting function to work, a singleton, or single node, must be specified; this is why the

positional predicate [1]must be specified Finally, the string is cast to xs:date (Note that

in the returnstatement, the string value of the same node is used.)

This example illustrates not only the type-related aspects of FLWOR expressions, but also

the capability to generate a root node without using FOR XML ROOT All that is required

is that a root node (in this case, Achievements), followed by curly braces, surround the

entire FLWOR statement.

Trang 4

The return Clause Similar to T-SQL’s SELECTstatement, the returnclause executes once

for every selected context node This is the section where you specify the structure and

content of the resulting XML The key aspect of it is the use of node constructors.

TIP

When using attribute constructors in thereturnclause, you need to make sure your

curly braces are directly adjacent to the attribute’s begin and end quotes, with no

whitespace in between (for example,attribute=”{$Node}”), or SQL Server raises an

error The reason is that string literals (even blank spaces) cannot be mixed with

attribute constructors.

Put simply, constructors create the nodes and node values to be output There are two

types of constructors:

Computed constructors—These are placed inside curly-braced expressions and

evaluated against the context node (for example, attribute=”{$N}”).

Direct constructors—These are constant node strings used in the FLWOR statement

(for example,<Achievements>) Listing 47.16 illustrates a variety of constructors.

LISTING 47.16 Using XQuery Constructors

SELECT Resume.query(‘

declare namespace

ns=”http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume”;

for $N in //ns:Education

return

<NodeConstructor attributeConstructor=”{string($N/ns:Edu.School[1])}”>

{ $N/ns:Edu.Major }

<?PI processing-instruction constructor PI?>

<! comment constructor >

</NodeConstructor>

‘)

FROM HumanResources.JobCandidate

WHERE JobCandidateId = 1

go

<NodeConstructor attributeConstructor=”Midwest State University”>

<ns:Edu.Major

xmlns:ns=”http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume”>

Mechanical Engineering

</ns:Edu.Major>

<?PI processing-instruction constructor PI?>

Trang 5

<! comment constructor >

</NodeConstructor>

Exactly the same XML result can be generated a third way: using the alternative

node-type-name constructors (for example, element,attribute,text) in a comma-delimited list

within curly braces Here’s an example:

SELECT Resume.query(‘

declare namespace

ns=”http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume”;

for $N in //ns:Education

return

element NodeConstructor

{

attribute attributeConstructor { string($N/ns:Edu.School[1])},

text { string($N/ns:Edu.Major[1]) },

<?PI processing-instruction constructor PI?>,

<! comment constructor >

}

‘)

FROM HumanResources.JobCandidate

WHERE JobCandidateId = 1

TIP

Becausequery()returns an instance of xml, the xmldata type methods can be

stacked on its result, allowing for powerful XQuery subqueries, such as

query(‘’).query(‘’).exist(‘’).

Testing XML by Using exist()

A common task when working with XML is the need to check for the existence of a node

or node value The exist()method does just that, returning 1if the node test returns

nonempty, or 0if empty.

Listing 47.17 tests whether the annual revenue of a surveyed store exceeds $100,000.

LISTING 47.17 Using exist() to Test for a Specific Node Value

WITH XMLNAMESPACES

(

DEFAULT

‘http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey’

)

SELECT Demographics.query(

Trang 6

for $N in /StoreSurvey

order by $N/AnnualSales

return

if ($N/AnnualSales >= 3000000)

then

<Money

Bank=”{$N/BankName}”

AnnualRevenue=”{$N/AnnualRevenue}”

AnnualSales=”{$N/AnnualSales}”

Comments=”really big bucks”/>

else

<Money

AnnualRevenue=”{$N/AnnualRevenue}”

AnnualSales=”{$N/AnnualSales}”

Comments=”big bucks”/>

‘)

FROM Sales.Store

WHERE Demographics.exist(‘

(//AnnualRevenue[xs:integer(.)>100000])

‘) = 1

go

<p1:Money

xmlns:p1=”http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey” AnnualRevenue=”150000” AnnualSales=”1500000”

Comments=”big bucks” />

<p1:Money

xmlns:p1=”http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey” AnnualRevenue=”150000” AnnualSales=”1500000”

Comments=”big bucks” />

<p1:Money

xmlns:p1=”http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey” AnnualRevenue=”150000” AnnualSales=”1500000”

Comments=”big bucks” />

<p1:Money

xmlns:p1=”http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey” AnnualRevenue=”150000” AnnualSales=”1500000”

Comments=”big bucks” />

<p1:Money

xmlns:p1=”http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/StoreSurvey” Bank=”International Bank” AnnualRevenue=”300000”

AnnualSales=”3000000” Comments=”really big bucks” />

{ }

Listing 47.17 also illustrates the use of the XQuery if-then-elseconstruct, which is used

to conditionally generate the BankNameattribute and change the value of the Comments

attribute In the WITH XMLNAMESPACESstatement that precedes the query, you use the

DEFAULTkeyword to specify a default namespace for the selection.

Trang 7

Converting a Node Value to a T-SQL Data Type by Using value()

Thevalue()function allows for a selected node value to be cast to a T-SQL–data typed

value It has two parameters: the first is a string-literal XPath expression that selects the

desired node value The second is a string-literal T-SQL data type name.

The code in Listing 47.18 queries an Extensible Application Markup Language (XAML)

document by using value()to select the Heightattribute of Canvasnodes and cast them

to decimal Notice that the returned results are rows rather than XML.

LISTING 47.18 Using value() to Retrieve and Convert a Node Value

WITH XMLNAMESPACES

(

‘http://schemas.microsoft.com/winfx/2006/xaml’ as x,

DEFAULT ‘http://schemas.microsoft.com/winfx/2006/xaml/presentation’

)

SELECT

IllustrationID,

Diagram.value(‘(//Canvas/@Height)[1]’, ‘decimal(16,4)’) HeightAsSQLDecimal

FROM Production.Illustration

go

IllustrationID HeightAsSQLDecimal

-

-3 147.7061

4 314.9819

5 105.7393

6 213.6152

7 177.5449

(5 row(s) affected)

Accessing Relational Columns and T-SQL Variables in XQuery Expressions Besidesvalue(),

two other bridges between T-SQL and XQuery are the XQuery functions sql:column()and

sql:variable().

sql:column(), as the name implies, allows for the selection of a relational column value

in a FLWOR statement In Listing 47.19, contact name data is pulled from Person.Person

into an XQuery element constructor and then selected back out again as a node value In

addition, the value of the declared T-SQL variable TotalPurchaseYTDis compared against

the value of the node of the same name in the XQuery whereclause, using

sql:variable().

LISTING 47.19 Using sql:column() and sql:variable() in XQuery

DECLARE @TotalPurchaseYTD decimal(6,2)

SET @TotalPurchaseYTD = 0

Trang 8

SELECT Demographics.query(‘

declare default element namespace

“http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/IndividualSurvey”;

for $IS in /IndividualSurvey

where $IS/TotalPurchaseYTD[.= sql:variable(“@TotalPurchaseYTD”)]

return

element Contact

{

attribute ID { sql:column(“C.BusinessEntityID”) },

attribute YTDTotal { sql:variable(“@TotalPurchaseYTD”) },

element FullName { concat(sql:column(“FirstName”), “ “,

sql:column(“LastName”)) }

}

‘)

FROM Sales.SalesPerson I

JOIN Person.Person C ON

C.BusinessEntityID = I.BusinessEntityID

AND C.BusinessEntityID = 285

concat()is one of several string functions built into XQuery, in addition to contains(),

substring(), and string-length().

Using the nodes() Method to Shred XML

In the section “XML as Relational Data: Using OPENXML,” earlier in this chapter, you

learned how to decompose XML directly into relational rows that could be mapped to

values in existing tables or used any other T-SQL way.

nodes()is kind of likeOPENXML’s big brother: given an XML input document and an

XQuery expression, it generates a table with anxmlcolumn against which subsequent

XQuery queries can be run.nodes()can be applied to bothxmlvariables andxmlcolumns.

Each row in the generated table contains a copy of the original input content The context

node for each row is based on the XQuery expression parameter It is possible to shred the

input in multiple ways by running multiple XQuery queries on the generated column in

the same SELECTstatement For example, one query might return a relational value from

each context node, using the value()method Another could transform and return each

content node to a different XML schema.

Let’s examine a simple example that shows how this works Listing 47.20 illustrates how

an XML document is shredded into relational rows and columns by applying six different

XQuery queries on each generated row, each of which creates a new relational column.

Trang 9

LISTING 47.20 Shredding XML Six Ways, Using nodes()

DECLARE @XmlVar xml

SET @XmlVar = ‘

<alphnumerics>

<item>

<alph name=”A” val=”65”/>

</item>

<item>

<alph name=”B” val=”66”/>

</item>

<item>

<alph name=”C” val=”67”/>

</item>

<item>

<num name=”1” val=”49”/>

</item>

<item>

<num name=”2” val=”50”/>

</item>

<item>

<num name=”3” val=”51”/>

</item>

</alphnumerics>’

SELECT

XmlTable.XmlColumn.query(‘alph’) AS ANode,

XmlTable.XmlColumn.value(‘alph[1]/@name’, ‘char(1)’) AS AName,

XmlTable.XmlColumn.value(‘alph[1]/@val’, ‘int’) AS AVal,

XmlTable.XmlColumn.query(‘num’) AS NNode,

XmlTable.XmlColumn.value(‘num[1]/@name’, ‘int’) AS NName,

XmlTable.XmlColumn.value(‘num[1]/@val’, ‘int’) AS NVal

FROM @XmlVar.nodes(‘/alphnumerics/item’) AS XmlTable(XmlColumn)

The syntax of nodes()is as follows:

nodes(XQuery) AS GeneratedTableName(GeneratedXmlColumnName)

Note that it is not possible to directly select the xmlcolumn generated by nodeswithout

using one of the xmldata type methods Using the XML from the preceding example, the

following code would raise an error:

SELECT XmlTable.XmlColumn

FROM @XmlVar.nodes(‘/alphnumerics/item’) AS XmlTable(XmlColumn)

You can also usenodes()withCROSS APPLYorOUTER APPLYto executenodes()once for

every row returned in the outer table In this way, you can combine relational data with

multiple XQuery queries against a relational rowset Listing 47.21 illustrates this technique.

Trang 10

LISTING 47.21 Using nodes() with CROSS APPLY

WITH XMLNAMESPACES(

‘http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume’ as ns

)

SELECT

JC.JobCandidateId,

E.BusinessEntityID,

ResumeTable.XmlColumn.value(‘ns:Emp.JobTitle[1]’, ‘nchar(50)’) JobTitle

FROM HumanResources.JobCandidate JC

CROSS APPLY JC.Resume.nodes(‘

/ns:Resume/ns:Employment[2]

‘) as ResumeTable(XmlColumn)

JOIN HumanResources.Employee E ON

E.BusinessEntityID = JC.BusinessEntityID

go

JobCandidateId EmployeeId JobTitle

-4 27 -4 Sales Associate

8 212

(2 row(s) affected.)

Using modify() to Insert, Update, and Delete XML

A frequent requirement when working with XML is the insertion, deletion, and

modifi-cation of nodes and node values These operations are known as XML Data Modifimodifi-cation

Language (XML DML) statements, and they are supported by thexmldata type’s

modify()method.

When you are working with typed XML, modify()performs type and structural checks

that allow operations to succeed only if they result in valid XML, so it’s important to

know your schema well.

When document order is important, it’s also crucial to know the exact location and

posi-tion of the nodes or values to be changed In the case of untyped or loosely constrained

typed XML, it may not matter all that much where a new node is placed.

XQuery provides a few functions and operators related to node order position()returns

the numeric position of a node (starting at 1).last()returns the numeric position of the

last node in a selected node list They are both performed against a context node.

In addition, you can use the node order comparison operators <<and>>to compare the

relative positions of two selected nodes The Boolean isoperator is also provided to test

whether two selected nodes are actually the same node.

modify()allows for three main operations in its XQuery expression parameter: insert,

replace value of, and delete Let’s look at deletefirst.

Ngày đăng: 05/07/2014, 02:20

TỪ KHÓA LIÊN QUAN