• Aucun résultat trouvé

EXPLICIT Mode Enhancements

Dans le document SQL Server (Page 177-184)

The following two enhancements have been made to the EXPLICITmode:

❑ CDATAdirective with an element name.

❑ elementxsinilcolumn mode.

Since an entire chapter, and a large one at that, could be spent on explaining the EXPLICITmode, this section assumes that this mode is not new to you or that you have at least a minimal understanding of the EXPLICITmode. To that end, the examples in this section highlight the enhancements of the EXPLICITmode and try to demonstrate a few more of its features while doing so.

With that, time to jump into some examples.

CDATA

This first example queries the Person.Contact table and builds an XML document with a CDATAsection wrapped in an <element>tag:

SELECT 1 AS Tag, 0 AS Parent,

ContactID as [Contact!1!ContactID], FirstName as [Contact!1!FirstName], LastName as [Contact!1!LastName],

‘<ContactInformation>Contact information</ContactInformation>’

as [Contact!1!!cdata]

FROM Person.Contact WHERE ContactID=218 FOR XML EXPLICIT Figure 8-9 shows the results.

Figure 8-9

In this example, ContactID, FirstName, and LastName are added as attributes to the Contactelement, and the CDATAsection is within the <ContactInformation>element.

Modify the previous example as follows and rerun the query:

SELECT 1 AS Tag, 0 AS Parent,

ContactID as [Contact!1!ContactID],

FirstName as [Contact!1!FirstName!ELEMENT], LastName as [Contact!1!LastName!ELEMENT],

‘<ContactInformation>Contact information</ContactInformation>’

as [Contact!1!!cdata]

FROM Person.Contact WHERE ContactID=218 FOR XML EXPLICIT

What is the shape of the results now? Adding the ELEMENTSdirective to the FOR XML EXPLICIT state-ment is not allowed; therefore if you want FirstNameand LastNamereturned as elements, you need to add the ELEMENTSdirective to the SELECTstatement as shown in the example. The results should look like those shown in Figure 8-10.

Figure 8-10

The CDATAdirective is used to wrap returned data in a CDATAsection. This directive is useful when you want to include text that typically would not be recognized as markup characters. In the example, the CDATAdirective was used to add information in its own element.

elementxsinil

The elementxsinildirective is used to generate elements for null values, meaning that if the query returns a null value, the elementxsinildirective still builds an element for that value with an attribute of xsi:nil=”true”.

Modify the example from the previous section to include the following:

SELECT 1 AS Tag, 0 AS Parent,

ContactID as [Contact!1!ContactID],

FirstName as [Contact!1!FirstName!ELEMENT],

MiddleName as [Contact!1!MiddleName!ELEMENTXSINIL], LastName as [Contact!1!LastName!ELEMENT],

‘<ContactInformation>Contact information</ContactInformation>’

as [Contact!1!!cdata]

FROM Person.Contact WHERE ContactID=483 FOR XML EXPLICIT

This example queries the Person.Contact table for a Contact. The MiddleName column uses the elementxsinildirective, telling the query that if the MiddleNamevalue for the specified ContactID is NULL, include an element for it anyway. The results for this query are shown in Figure 8-11.

Figure 8-11

Sure enough, the MiddleName for ContactID 483 is NULL, but an element for the MiddleName was included anyway. What happens if the elementxisnildirective is used and a MiddleName is not NULL? Modify the query, changing the WHEREstatement to query for ContactID of 218 and rerun the query.

In the case where the elementxisnildirective is specified but the value returned is not NULL, the elementxisnildirective is basically ignored and the value is included in the MiddleNameelement, as shown in Figure 8-12.

Figure 8-12

In both examples, using the elementxisnildirective, notice that the root Contact element includes a namespace.

Specifying the TYPEdirective is allowed, which lets you return these results as xmldata type.

PATH Mode

It is no secret, as you found out in the last section or probably already know: dealing with the EXPLICIT mode is exquisitely painful. The upside to this mode is that it provides the greatest flexibility when shaping XML results. The downside is that the learning curve is steep.

The moans and groans from all over the world were heard loud and clear at Microsoft headquarters in Redmond, Washington; thus the PATHmode is introduced in SQL Server 2005 to ease the EXPLICIT mode pains.

The goal of the PATHmode is to provide an easier way to generate XML documents with much easier queries. The PATHmode provides a painless way to mix attributes and elements and can be used to return results as the xmldata type using the TYPEdirective. And as you will learn about in the next section, it also can be used with nesting FOR XMLqueries.

The PATHmode takes all columns returned from a SELECTquery and maps them to attributes and ele-ments using an XPath-like syntax.

The PATHmode is specified by adding the PATHdirective to the FOR XMLclause, as follows:

FOR XML PATH

Jumping right in to examples, the following example queries four columns from the Person.Contact table; the fourth column does not specify a column name, but the PATHmode inserts an XML instance with the returned data in the query:

SELECT ContactID, FirstName,

LastName,

AdditionalContactInfo.query(‘

declare namespace PC=”http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ContactTypes”;

/PC:telephoneNumber/PC:number

‘)

FROM Person.Contact WHERE ContactID = 10 FOR XML PATH

GO

Any column that does not specify a name is included in-line, meaning properly nested within the XML instance, as shown in Figure 8-13.

Figure 8-13

Column names returned in the rowset are mapped case-sensitive to the results in the XML instance. For example, the following code simply queries the Person.Contact table creating an alias column called

@PCID:

SELECT ContactID as “@PCID”, FirstName,

LastName

FROM Person.Contact WHERE ContactID = 218 The results look like this:

@PCID FirstName LastName --- - ---218 Scott Colvin

Adding the FOR XML PATHstatement to the query, as in the following example, the column name from the first query begins with an at symbol (@), and therefore is mapped to an attribute of the <row> col-umn with the value associated to it:

SELECT ContactID as “@PCID”, FirstName,

LastName

FROM Person.Contact WHERE ContactID = 218 FOR XML PATH

GO

Figure 8-14 shows the resulting XML instance.

Figure 8-14

When generating this kind of query, the attribute needs to come before the other columns or else an error is generated. For example, the following will fail:

SELECT FirstName, ContactID as “@PCID”

FROM Person.Contact WHERE ContactID = 218 FOR XML PATH

GO

The basic rule of thumb to remember is that if the column name in the rowset does not begin with @, but begins with a forward slash (/), then XML hierarchy is applied. In the preceding example, the column name began with @; therefore the PATHmode mapped it as an attribute.

In the following example, four columns are returned. The first column begins with @, so it is mapped to an attribute. The other three columns contain a /, so the XML hierarchy is applied:

SELECT EmployeeID “@EmpID”, FirstName “EmpName/First”, MiddleName “EmpName/Middle”, LastName “EmpName/Last”

FROM HumanResources.Employee E, Person.Contact C WHERE E.EmployeeID = C.ContactID

AND E.EmployeeID=218 FOR XML PATH

Figure 8-15 shows the resulting XML instance.

Figure 8-15

The XML instance can be further shaped by making the following changes to the query:

SELECT EmployeeID “@EmpID”, FirstName “EmpName/First”,

MiddleName “EmpName/MiddleName/Middle”, LastName “EmpName/Last”

FROM HumanResources.Employee E, Person.Contact C WHERE E.EmployeeID = C.ContactID

AND E.EmployeeID=218

The results now look like Figure 8-16.

Figure 8-16

In this example, the query was modified to have the <Middle>node show up a level deeper, a child of the <MiddleName>node. This was accomplished by telling the results to add another layer for this node.

As you learned earlier, if the query returns a NULLvalue, the element is not mapped. To generate ele-ments for a NULLvalue, specify the ELEMENTS XSINILdirective. The ELEMENTS XSINILdirective is very similar to the NULLexample given earlier in the chapter except for the placement and slight differ-ence in syntax. The functionality is the same, but in this case the placement of the directive is after the FOR XMLclause and it is two words, not one. Note also the change in the ContactID for this example:

SELECT EmployeeID “@EmpID”, FirstName “EmpName/First”,

MiddleName “EmpName/MiddleName/Middle”, LastName “EmpName/Last”

FROM HumanResources.Employee E, Person.Contact C WHERE E.EmployeeID = C.ContactID

AND E.EmployeeID=236 FOR XML PATH, ELEMENTS XSINIL

This next example specifies multiple paths and maps the columns accordingly:

SELECT EmployeeID “@EmpID”, FirstName “Contact/First”, MiddleName “Contact/Middle”, LastName “Contact/Last”, Birthdate “Employee/Birthdate”, HireDate “Employee/HireDate”

FROM HumanResources.Employee E, Person.Contact C WHERE E.ContactID = C.ContactID

AND E.EmployeeID=218 FOR XML PATH

The results are shown in Figure 8-17.

Figure 8-17

In the previous example the columns were nice and orderly. What happens if that order is tossed around like this:

SELECT EmployeeID “@EmpID”, FirstName “Contact/First”, Birthdate “Employee/Birthdate”, MiddleName “Contact/Middle”, HireDate “Employee/HireDate”, LastName “Contact/Last”

FROM HumanResources.Employee E, Person.Contact C WHERE E.ContactID = C.ContactID

AND E.EmployeeID=1 FOR XML PATH

The columns are returned as shown in Figure 8-18. The PATHdirective nests the elements as they appear in the SELECTstatement, and cannot order them as shown previously in Figure 8-17.

Figure 8-18

The results in Figure 8-18 look different than they do in Figure 8-17 because the PATHdirective nests the elements as they appear in the SQL statement. In the case of Figure 8-18, because the order was mixed, the query returned the results with each value in its own node instead of grouping them like Figure 8-17.

One more example for this section:

SELECT EmployeeID “@EmployeeID”,

‘Employee Information’ as “text()”,

‘MiddleName is optional’ as “EmpName/text()”, FirstName as “EmpName/First”, MiddleName as “EmpName/Middle”, LastName as “EmpName/Last”, Birthdate as “Employee/Birthdate”, HireDate as “Employee/HireDate”

FROM HumanResources.Employee E, Person.Contact C WHERE E.EmployeeID = C.ContactID

AND E.EmployeeID=218 FOR XML PATH

In this query, an XPath node test of text()is used in two places. First, it is used to add a string after the root node <row>, and the second use adds a text string after the <EmpName>element. The results in Figure 8-19 show the text().

Figure 8-19

The PATHmode, as you should be able to tell by now, is a much welcomed addition to SQL Server 2005 and a much simpler method of mixing elements and attributes over the cumbersome EXPLICITmode.

Speaking of new enhancements to SQL Server 2005, it’s time to talk about another one.

Dans le document SQL Server (Page 177-184)