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

Hướng dẫn học Microsoft SQL Server 2008 part 51 pot

10 243 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 396,76 KB

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

Nội dung

It then uses theHIDEdirective to instruct SQL Server that the column should not be included in the XML output: SELECT 1 AS Tag, NULL AS Parent, CustomerNumber AS ‘Order!1!CustNo’, OrderN

Trang 1

<LineItems ItemNo="D001" Qty="1" />

</Order>

</Orders>

*/

Though the root element is correctly added, the XML output is not in the required structure In fact, the

information given is incorrect, because it shows that all three line items belong to Order SO102

This behavior is caused by the fact that the XML generator consumes rows in the same order as they are

returned by theSELECTquery To generate the results in the correct order, theSELECTquery should

contain anORDER BYclause that controls the order of the rows in the result set

The following example shows a new version of the query that generates a column just for the purpose of

sorting It then uses theHIDEdirective to instruct SQL Server that the column should not be included

in the XML output:

SELECT

1 AS Tag, NULL AS Parent, CustomerNumber AS ‘Order!1!CustNo’, OrderNumber AS ‘Order!1!OrderNo’, REPLACE(STR(OrderID,4) + STR(0,4),’ ‘,’0’) AS ‘Order!1!Sort!HIDE’, NULL AS ‘LineItems!2!ItemNo’,

NULL AS ‘LineItems!2!Qty’

FROM OrderHeader o INNER JOIN Customers c ON o.CustomerID = c.CustomerID UNION ALL

SELECT

2 AS Tag,

1 AS Parent, NULL, NULL, REPLACE(STR(OrderID,4) + STR(OrderDetailID,4),’ ‘,’0’), i.ItemNumber,

o.Quantity FROM Items i INNER JOIN OrderDetails o ON i.ItemID = o.ItemID ORDER BY ‘Order!1!Sort!HIDE’

FOR XML EXPLICIT, ROOT(’Orders’) /*

<Orders>

<Order CustNo="J001" OrderNo="SO101">

<LineItems ItemNo="D001" Qty="1" />

<LineItems ItemNo="Z001" Qty="1" />

</Order>

<Order CustNo="J001" OrderNo="SO102">

<LineItems ItemNo="D001" Qty="1" />

</Order>

</Orders>

*/

Trang 2

That query could produce the correct result because of theORDER BYclause present in the query The

ORDER BYclause ensures that the first row is the order header information for SO101 and that the next

two rows contain order detail information for the same order Again, it ensures that the next row is

order header information for SO102, followed by the order detail information of the same order The

query returns the following result set (column names abridged for space):

Tag Parent CustNo OrderNo Sort!HIDE ItemNo Qty

- -

1 NULL J001 SO10 00010000 NULL NULL

2 1 NULL NULL 00010001 D001 1

2 1 NULL NULL 00010002 Z001 1

1 NULL J001 SO10 00020000 NULL NULL

2 1 NULL NULL 00020003 D001 1

As clearly apparent from the example, theORDER BYclause has arranged the rows in the correct order

using the arbitrary sort column This result set is consumed by the XML generator and the output XML

is generated in the correct order

One of the most common problems that people face withFOR XML EXPLICITis ordering It will be

helpful in such cases to run the query without theFOR XMLclause and inspect the output to ensure

that the rows are in the correct order

FOR XML EXPLICITsupports a few more interesting directives, such asXML,XMLTEXT, andCDATA

The XML directive behaves very similarly to theELEMENTdirective The only difference is that

ELEMENTentitizes XML tags andXMLpreserves the XML tags:

SELECT

1 AS Tag,

NULL AS Parent,

‘<Info about="XML"/>’ AS ‘MyData!1!!ELEMENT’

FOR XML EXPLICIT

/*

ELEMENT directive encodes XML tags

<MyData>&lt;Info about="XML"/&gt;</MyData>

*/

SELECT

1 AS Tag,

NULL AS Parent,

‘<Info about="XML"/>’ AS ‘MyData!1!!XML’

FOR XML EXPLICIT

/*

XML directive preserves XML tags

<MyData>

<Info about="XML" />

</MyData>

*/

TheXMLTEXTdirective wraps the column content in a single tag and integrates it with the rest of the

document:

SELECT

1 AS Tag,

NULL AS Parent,

Trang 3

‘<Info about="XML"/>’ AS ‘MyData!1!!XMLTEXT’

FOR XML EXPLICIT /*

<MyData about="XML"></MyData>

*/

TheCDATAdirective wraps the value within a CDATA block in the output XML document.EXPLICIT

is the only directive that can generate a CDATA section:

SELECT

1 AS Tag, NULL AS Parent,

‘<Info about="XML"/>’ AS ‘MyData!1!!CDATA’

FOR XML EXPLICIT /*

<MyData><![CDATA[<Info about="XML"/>]]></MyData>

*/

TheID,IDREF, andIDREFSdirectives can be used to create intra-document links

Another helpful directive thatFOR XML EXPLICITsupports isELEMENTXSINIL The behavior of this

directive is very similar to theXSINILdirective supported byAUTOandRAW It is explained in the

section ‘‘XSINIL Directive’’ later in this chapter

FOR XML PATH

FOR XML PATHwas introduced in SQL Server 2005 It is a lightweight alternative toFOR XML

EXPLICIT.FOR XML PATHis as powerful asFOR XML EXPLICITand as simple asFOR XML AUTO

andRAW

The previous section demonstrated the complexity of using aFOR XML EXPLICITquery.FOR XML

PATHhas a simple syntax and supports generating almost all XML document structures previously

possible only withFOR XML EXPLICIT

The true power ofFOR XML PATHcan be experienced when the XML structure is complex and has a

multi-level hierarchy It may be interesting to compare the complexity of code needed to produce the

same XML document usingFOR XML EXPLICITandFOR XML PATH

The following example shows a sample XML document that will be generated usingFOR XML PATH

andFOR XML EXPLICITto see the extent of the simplicity thatFOR XML PATHprovides to the SQL

programmer:

<Orders>

<Order OrderNumber="SO102">

<Customer CustomerNumber="J001" />

<LineItems>

<Item ItemNo="D001" Qty="1" />

</LineItems>

</Order>

</Orders>

Trang 4

The preceding XML document contains information about a sales order The following example shows

theFOR XML EXPLICITcode needed to produce the preceding output:

SELECT

1 AS Tag,

NULL AS Parent,

OrderNumber AS ‘Order!1!OrderNumber’,

NULL AS ‘Customer!2!CustomerNumber’,

NULL AS ‘LineItems!3!’,

NULL AS ‘Item!4!ItemNo’,

NULL AS ‘Item!4!Qty’

FROM OrderHeader oh

WHERE OrderID = 2

UNION ALL

SELECT

2 AS Tag,

1 AS Parent,

NULL,

c.CustomerNumber,

NULL, NULL, NULL

FROM OrderHeader oh

INNER JOIN Customers c ON oh.CustomerID = c.CustomerID

AND OrderID = 2

UNION ALL

SELECT

3 AS Tag,

1 AS Parent,

NULL,

NULL,

NULL, NULL, NULL

UNION ALL

SELECT

4 AS Tag,

3 AS Parent,

NULL, NULL, NULL,

i.ItemNumber, od.Quantity

FROM OrderDetails od

INNER JOIN Items i ON i.ItemID = od.ItemID

AND od.OrderID = 2

FOR XML EXPLICIT,ROOT(’Orders’)

/*

<Orders>

<Order OrderNumber="SO102">

<Customer CustomerNumber="J001" />

<LineItems>

<Item ItemNo="D001" Qty="1" />

</LineItems>

</Order>

</Orders>

*/

Trang 5

The following example shows theFOR XML PATHquery needed to produce the same XML output:

SELECT oh.OrderNumber AS ‘@OrderNumber’, c.CustomerNumber AS ‘Customer/@CustomerNumber’, i.ItemNumber AS ‘LineItems/Item/@ItemNo’, od.Quantity AS ‘LineItems/Item/@Qty’

FROM OrderHeader oh INNER JOIN Customers c ON oh.CustomerID = c.CustomerID AND OrderID = 2

INNER JOIN OrderDetails od ON od.OrderID = oh.OrderID INNER JOIN Items i ON i.ItemID = od.ItemID

FOR XML PATH(’Order’),ROOT(’Orders’) /*

<Orders>

<Order OrderNumber="SO102">

<Customer CustomerNumber="J001" />

<LineItems>

<Item ItemNo="D001" Qty="1" />

</LineItems>

</Order>

</Orders>

*/

The amount of simplicity and power that comes withFOR XML PATHis apparent from the preceding

example The true power comes from the fact thatFOR XML PATHallows generating deep hierarchies

based on the column name The column nameLineItems/Item/@Qtycreates anItemelement with

aQtyattribute underLineItems An attribute is created by prefixing the name with an@sign:

SELECT CustomerID AS ‘@CustomerID’, OrderNumber AS ‘OrderNumber’

FROM OrderHeader FOR XML PATH(’Order’), ROOT(’Orders’) /*

<Orders>

<Order CustomerID="1">

<OrderNumber>SO101</OrderNumber>

</Order>

<Order CustomerID="1">

<OrderNumber>SO102</OrderNumber>

</Order>

</Orders>

*/

FOR XML PATHsupports a number of special characters to achieve different XML formatting

require-ments For example, a ‘‘mixed’’ type element (an element that has a text value as well as attributes) can

be created by naming a column with an asterisk (‘‘*’’), as shown in the following example:

SELECT CustomerID AS ‘@CustomerID’,

Trang 6

OrderNumber AS ‘*’

FROM OrderHeader

FOR XML PATH(’Order’), ROOT(’Orders’)

/*

<Orders>

<Order CustomerID="1">SO101</Order>

<Order CustomerID="1">SO102</Order>

</Orders>

*/

The same result can be obtained by using the special column name indicatorsdata(),node(),

ortext()

Thedata()indicator can also be used to generate a space-separated list of values by making thePATH

name empty:

SELECT

ItemNumber AS ‘data()’

FROM Items

FOR XML PATH(’’), ROOT(’Items’)

/*

<Items>D001 Z001</Items>

*/

Using thetext()indicator along with emptyPATHname will generate a similar string, but without

spaces between the values:

SELECT

ItemNumber AS ‘text()’

FROM Items

FOR XML PATH(’’), ROOT(’Items’)

/*

<Items>D001Z001</Items>

*/

Finally, a comment can be generated using the special column name indicatorcomment()along with

FOR XML PATH:

SELECT

‘Order Number’ AS ‘comment()’,

OrderNumber,

‘Customer ID’ AS ‘comment()’,

CustomerID

FROM OrderHeader WHERE OrderID = 1

FOR XML PATH(’’), ROOT(’Orders’)

/*

<Orders>

<! Order Number >

<OrderNumber>SO101</OrderNumber>

<! Customer ID >

Trang 7

</Orders>

*/

FOR XML PATHis both powerful and easy to use It offers a great deal of control over the structure of

the output document Most operations previously possible only with complexFOR XML EXPLICIT

queries are now possible withFOR XML PATH

TYPE directive

AFOR XMLquery returns a result set with one row and one column containing anNVARCHAR(MAX)

value TheTYPEdirective can be used to request SQL Server to return anXMLdata type value,

instead ofNVARCHAR(MAX).FOR XMLqueries can take advantage of theTYPEdirective in a number

of ways

FOR XML AUTOandRAWare relatively simple to use, but they provide very little control over the

struc-ture of the XML result TheTYPEdirective can be used to write nestedFOR XMLqueries withFOR XML

AUTOandRAW, which offers greater control over the structure of the XML output

For example, the following XML output cannot be achieved withFOR XML AUTOorRAWwithout using

a nestedFOR XMLquery:

<SalesOrder OrderNumber="SO101">

<Customer CustomerNumber="J001" Name="Jacob Sebastian"/>

<Items>

<Item ItemNumber="D001" Quantity="1" Price="900.0000" />

<Item ItemNumber="Z001" Quantity="1" Price="200.0000" />

</Items>

</SalesOrder>

The following example shows a nestedFOR XML AUTOquery that generates the preceding XML output:

SELECT SalesOrder.OrderNumber, SalesOrder.OrderDate, ( SELECT CustomerNumber, Name FROM Customers Customer FOR XML AUTO, TYPE ), ( SELECT ItemNumber, Quantity, Price FROM (

SELECT i.ItemNumber, o.Quantity, o.Price FROM Items i INNER JOIN OrderDetails o ON i.ItemID = o.ItemID WHERE OrderID = 1

) Item FOR XML AUTO, ROOT(’Items’),TYPE )

Trang 8

FROM OrderHeader SalesOrder

WHERE OrderID = 1

FOR XML AUTO

Because theTYPEdirective generates anXMLdata type value, instead ofNVARCHAR(MAX), the result

of aFOR XMLquery that uses theTYPEdirective can be used as input for other XML operations The

following example demonstrates this:

SELECT

(

SELECT OrderID, CustomerID

FROM OrderHeader

FOR XML AUTO, TYPE

).value(’(OrderHeader/@OrderID)[1]’,’INT’) AS OrderID

/*

OrderID

-1

*/

The inner query in the preceding example returns anXMLdata type value and hence it is possible to

invokeXMLdata type methods such asvalue()orquery()on theFOR XMLquery result

XSINIL Directive

Let us look at two examples:

Example 1:

<Employee>

<FirstName>Jacob</FirstName>

<Employee>

Example 2:

<Employee>

<FirstName>Jacob</FirstName>

<HireDate xsi:nil="true" />

<Employee>

Example 3:

<Employee>

<FirstName>Jacob</FirstName>

<HireDate >1900-01-01</HireDate>

</Employee>

By default,FOR XMLdoes not include columns withNULLvalues in the XML output Some applications

might need to process missing values different fromNULLvalues Those applications might require

that an XML element be present in the XML document, even if the value isNULL.FOR XMLsupports a

Trang 9

special directive,XSINIL, that helps to achieve this.XSINILis applicable only to elements, and can

be used only with theELEMENTSdirective WhenXSINILis specified,FOR XMLgenerates an empty

element for any column that has aNULLvalue:

SELECT OrderNumber, CustomerID, NULL AS CustomerPhone FROM OrderHeader [Order]

FOR XML AUTO, ELEMENTS XSINIL /*

<Order xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<OrderNumber>SO101</OrderNumber>

<CustomerID>1</CustomerID>

<CustomerPhone xsi:nil="true" />

</Order>

*/

Note that an emptyCustomerPhoneelement is created in the preceding example, along with a special

attributexsi:nilset to ˝ true˝ It signals the XML parser that the element has aNULLvalue

Generating XML Schema information

FOR XML AUTOandRAWprovide very little control over the structure of the XML document The

docu-ment is usually structured based on the tables, columns, and joins used in theSELECTquery Because

the structure of the XML document is based on the order of the columns in the select list and the way

joins are applied in the query, it is important to tell any applications that consume the XML result about

the structure of the XML document

An XML document is usually described using a schema SQL Server can generate an XML or XDR (XML

Data Reduced) schema along with the query results of aFOR XML AUTOorRAWquery

FOR XML EXPLICITandPATHare usually used to generate XML documents as per a given structure or

schema; hence, support for generating schema information is not available with these options

An XDR schema can be generated along with the output by specifying theXMLDATAdirective as part of

theFOR XMLquery:

SELECT OrderNumber, CustomerID FROM OrderHeader [Order]

FOR XML AUTO, XMLDATA Similarly, theXMLSCHEMAdirective can be used to generate an XML schema describing the output XML

document:

SELECT OrderNumber, CustomerID FROM OrderHeader [Order]

FOR XML AUTO, XMLSCHEMA

Trang 10

A client application that processes the XML output will read the inline schema information before

processing the XML document and understand the structure of the XML document An optional target

namespace can be specified along with theXMLSCHEMAdirective If a target namespace is specified, the

XML output will be generated with a target namespace declaration:

SELECT

OrderNumber, CustomerID

FROM OrderHeader [Order]

FOR XML AUTO, XMLSCHEMA(’urn:some-namespace’)

Generating XML namespaces

XML uses namespaces to resolve ambiguity between elements or attributes referring to different contexts

All programming languages use some kind of operators to resolve ambiguity T-SQL uses table aliases to

resolve ambiguity — for example, ‘‘employee.name’’ is differentiated from ‘‘department.name.’’ NET uses

namespaces to avoid conflicts between objects inherited from different libraries

Similarly, XML documents use namespaces to avoid conflicts between elements or attributes with the

same name AFOR XMLquery can generate an XML document that contains one or more namespace

declarations The following code demonstrates an example that generates an XML document with a

namespace declaration:

;WITH XMLNAMESPACES(

‘http://www.sqlserverbible.com/orders’ AS ord

)

SELECT

CustomerID AS ‘@CustomerID’,

OrderNumber AS ‘data()’

FROM OrderHeader

FOR XML PATH(’Order’),ROOT(’Orders’)

/*

<Orders xmlns:ord="http://www.sqlserverbible.com/orders">

<Order CustomerID="1">SO101</Order>

<Order CustomerID="1">SO102</Order>

</Orders>

*/

A default namespace declaration can be added by using theDEFAULTclause along with the namespace

declaration:

;WITH XMLNAMESPACES(

DEFAULT ‘http://www.sqlserverbible.com/orders’

)

SELECT

CustomerID AS ‘@CustomerID’,

OrderNumber AS ‘data()’

FROM OrderHeader

FOR XML PATH(’Order’),ROOT(’Orders’)

/*

Ngày đăng: 04/07/2014, 09:20

TỪ KHÓA LIÊN QUAN