Using the FOR XML Clause to Return Query Results as XML:
SQL Server lets you retrieve data as XML by supporting the FOR XML clause, which can be included as part of your query. You can use the FOR XML
clause in the main (outer) query as well as in subqueries. The clause
supports numerous options that let you define the format of the XML
data.
When you include the FOR XML clause in your query, you must specify one of the four supported modes—RAW, AUTO, EXPLICIT, or PATH.
The options available to each mode vary according to that mode;
however, many of the options are shared among the modes. In this
article, I explain how to use each of these modes to retrieve data as
XML and provide examples that demonstrate how they use the various
options. The RAW Mode
The RAW mode generates a single XML element for each row in the result set returned by the query.To use the FOR XML clause in RAW mode, you simply append the clause and RAW keyword to your SELECT statement, as shown in the following example:
SELECT e.EmployeeID, c.FirstName, c.MiddleName, c.LastName
FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML RAW;
Notice that the SELECT statement itself is a very basic query. (The statement pulls data from the AdventureWorks sample database.) Without the FOR XML clause, the statement would return the following results:FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML RAW;
EmployeeID FirstName MiddleName LastName
---------- --------- ---------- --------
4 Rob NULL Walters
168 Rob T Caron
With the addition of the FOR XML clause, the statement returns the data as the following XML:---------- --------- ---------- --------
4 Rob NULL Walters
168 Rob T Caron
Note: You can include a FOR XML clause only in SELECT
statements, if those statements define the outer, or top-level, query.
However, you can also include the clause in INSERT, UPDATE, and DELETE
statements that are part of a subquery.
SELECT e.EmployeeID, c.FirstName, c.MiddleName, c.LastName
FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML RAW ('Employee');
Now the element associated with each row returned by the query will be named FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML RAW ('Employee');
In addition to being able to provide a name for the row element, you can also specify that a root element be created to wrap all other elements. To create a root element, add the ROOT keyword to your FOR XML clause:
SELECT e.EmployeeID, c.FirstName, c.MiddleName, c.LastName
FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML RAW ('Employee'), ROOT;
Notice that you must include a comma when adding an option such as
ROOT in order to separate the elements. As the following results show, a
FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML RAW ('Employee'), ROOT;
SELECT e.EmployeeID, c.FirstName, c.MiddleName, c.LastName
FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML RAW ('Employee'), ROOT ('Employees');
In this case, I’ve named the root element FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML RAW ('Employee'), ROOT ('Employees');
SELECT e.EmployeeID, c.FirstName, c.MiddleName, c.LastName
FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML RAW ('Employee'), ROOT ('Employees'), ELEMENTS;
Once again, I’ve added a comma to separate the options. As you can see in the following results, each FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML RAW ('Employee'), ROOT ('Employees'), ELEMENTS;
If you refer back to the XML returned by the previous example, you’ll notice that the data for employee 4 (Rob Walters) does not include a middle name. This is because that MiddleName value is null in the source data, and by default, no elements are created for a column whose value is null. However, you can override this behavior by adding the XSINIL keyword to the ELEMENTS option:
SELECT e.EmployeeID, c.FirstName, c.MiddleName, c.LastName
FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML RAW ('Employee'), ROOT ('Employees'), ELEMENTS XSINIL;
Now the results will include an element for the MiddleName column and will include the xsi:nil attribute with a value of true when a value is null, as shown in the following XML:FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML RAW ('Employee'), ROOT ('Employees'), ELEMENTS XSINIL;
Another important option that is supported by the RAW node is XMLSCHEMA, which specifies that an inline W3C XML Schema (XSD) be included in the XML data. You add the XMLSCHEMA option in the same way you add other options:
SELECT e.EmployeeID, c.FirstName, c.MiddleName, c.LastName
FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML RAW ('Employee'), ROOT ('Employees'), ELEMENTS XSINIL, XMLSCHEMA;
As you can see in the following results, the schema is fully defined and is incorporated in the XML results:FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML RAW ('Employee'), ROOT ('Employees'), ELEMENTS XSINIL, XMLSCHEMA;
SELECT e.EmployeeID, c.FirstName, c.MiddleName, c.LastName
FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML RAW ('Employee'), ROOT ('Employees'), ELEMENTS XSINIL,
XMLSCHEMA ('urn:schema_example.com');
The statement will return the same results as the previous example,
except that the XML will now include the new name of the target
namespace.FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML RAW ('Employee'), ROOT ('Employees'), ELEMENTS XSINIL,
XMLSCHEMA ('urn:schema_example.com');
The SELECT statements shown in the preceding examples have retrieved data from non-XML columns (in this case, integer and string columns). However, your queries might also retrieve data from XML columns. In such cases, the FOR XML clause will incorporate the data retrieved from an XML column into the XML result set.
For example, the following SELECT statement uses the XML query() method to retrieve education-related data from the Resume column in the JobCandidate table:
SELECT e.EmployeeID, c.FirstName, c.LastName,
jc.Resume.query('declare namespace ns=
"http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
/ns:Resume/ns:Education')
FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON c.ContactID = e.ContactID
INNER JOIN HumanResources.JobCandidate jc
ON e.EmployeeID = jc.EmployeeID
WHERE e.EmployeeID = 268
FOR XML RAW ('Employee'), ELEMENTS;
The query() method itself retrieves the following data from the Resume column:jc.Resume.query('declare namespace ns=
"http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
/ns:Resume/ns:Education')
FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON c.ContactID = e.ContactID
INNER JOIN HumanResources.JobCandidate jc
ON e.EmployeeID = jc.EmployeeID
WHERE e.EmployeeID = 268
FOR XML RAW ('Employee'), ELEMENTS;
The AUTO Mode
The AUTO mode in a FOR XML clause is slightly different from the RAW mode in the way that it generates the XML result set. The AUTO mode generates the XML by using heuristics based on how the SELECT statement is defined. The best way to understand how this works is to look at an example. The following SELECT statement, as in the previous examples, retrieves employee data from the AdventureWorks database:
SELECT Employee.EmployeeID, ContactInfo.FirstName,
ContactInfo.MiddleName, ContactInfo.LastName
FROM HumanResources.Employee AS Employee
INNER JOIN Person.Contact AS ContactInfo
ON ContactInfo.ContactID = Employee.ContactID
WHERE ContactInfo.FirstName = 'Rob'
FOR XML AUTO, ROOT ('Employees');
Notice that I’ve provided meaningful alias names to the tables (Employee and Contact info). These names are used in defining the XML element names, so you’ll want to construct your SELECT statements accordingly. Now take a look at the results returned by this query:ContactInfo.MiddleName, ContactInfo.LastName
FROM HumanResources.Employee AS Employee
INNER JOIN Person.Contact AS ContactInfo
ON ContactInfo.ContactID = Employee.ContactID
WHERE ContactInfo.FirstName = 'Rob'
FOR XML AUTO, ROOT ('Employees');
In addition, the columns and their values are added as attributes to the table-related elements. This structure is similar to what you saw in the RAW mode examples. And in the same way, you can override the default behavior by using the ELEMENTS option:
SELECT Employee.EmployeeID, ContactInfo.FirstName,
ContactInfo.MiddleName, ContactInfo.LastName
FROM HumanResources.Employee AS Employee
INNER JOIN Person.Contact AS ContactInfo
ON ContactInfo.ContactID = Employee.ContactID
WHERE ContactInfo.FirstName = 'Rob'
FOR XML AUTO, ROOT ('Employees'), ELEMENTS;
As you can see in the following XML result set, the column values are now included as child elements, rather than attributes:ContactInfo.MiddleName, ContactInfo.LastName
FROM HumanResources.Employee AS Employee
INNER JOIN Person.Contact AS ContactInfo
ON ContactInfo.ContactID = Employee.ContactID
WHERE ContactInfo.FirstName = 'Rob'
FOR XML AUTO, ROOT ('Employees'), ELEMENTS;
If you want to include an element for columns with null values, you can use the XSINIL option, as you saw when using the RAW mode:
SELECT ContactInfo.FirstName, ContactInfo.MiddleName,
ContactInfo.LastName, Employee.EmployeeID
FROM HumanResources.Employee AS Employee
INNER JOIN Person.Contact AS ContactInfo
ON ContactInfo.ContactID = Employee.ContactID
WHERE ContactInfo.FirstName = 'Rob'
FOR XML AUTO, ROOT ('Employees'), ELEMENTS XSINIL;
Now the results will include all elements. That means, if a value is null, the xsi:nil attribute is included:ContactInfo.LastName, Employee.EmployeeID
FROM HumanResources.Employee AS Employee
INNER JOIN Person.Contact AS ContactInfo
ON ContactInfo.ContactID = Employee.ContactID
WHERE ContactInfo.FirstName = 'Rob'
FOR XML AUTO, ROOT ('Employees'), ELEMENTS XSINIL;
For example, the following SELECT statement includes the FullName computed column, which concatenates the first and last names:
SELECT Employee.EmployeeID,
(ContactInfo.FirstName + ' ' + ContactInfo.LastName) AS FullName,
ContactInfo.EmailAddress
FROM HumanResources.Employee AS Employee
INNER JOIN Person.Contact AS ContactInfo
ON ContactInfo.ContactID = Employee.ContactID
WHERE ContactInfo.FirstName = 'Rob'
FOR XML AUTO, ROOT ('Employees'), ELEMENTS XSINIL;
Because the FullName column appears in the SELECT list after the EmployeeID column, the FullName column is added as a child element of (ContactInfo.FirstName + ' ' + ContactInfo.LastName) AS FullName,
ContactInfo.EmailAddress
FROM HumanResources.Employee AS Employee
INNER JOIN Person.Contact AS ContactInfo
ON ContactInfo.ContactID = Employee.ContactID
WHERE ContactInfo.FirstName = 'Rob'
FOR XML AUTO, ROOT ('Employees'), ELEMENTS XSINIL;
SELECT Employee.EmployeeID, ContactInfo.EmailAddress,
(ContactInfo.FirstName + ' ' + ContactInfo.LastName) AS FullName
FROM HumanResources.Employee AS Employee
INNER JOIN Person.Contact AS ContactInfo
ON ContactInfo.ContactID = Employee.ContactID
WHERE ContactInfo.FirstName = 'Rob'
FOR XML AUTO, ROOT ('Employees'), ELEMENTS XSINIL;
Now the FullName column will be added as a child element to the (ContactInfo.FirstName + ' ' + ContactInfo.LastName) AS FullName
FROM HumanResources.Employee AS Employee
INNER JOIN Person.Contact AS ContactInfo
ON ContactInfo.ContactID = Employee.ContactID
WHERE ContactInfo.FirstName = 'Rob'
FOR XML AUTO, ROOT ('Employees'), ELEMENTS XSINIL;
Now let’s take a look at another aspect of the AUTO mode. One of the limitations of this mode (as well as the RAW mode) is that the column data is added as either attributes or child elements, depending on whether you specify the ELEMENTS option. However, there might be times when you want to return some of the data as attributes and some as child elements. One method you can use with the AUTO mode is to return some of the data in a subquery. For example, the following SELECT statement includes a subquery that returns the employee’s first and last names:
SELECT EmployeeID, LoginID,
(SELECT FirstName, LastName
FROM Person.Contact AS EmployeeName
WHERE EmployeeName.ContactID = Employee.ContactID
FOR XML AUTO, TYPE, ELEMENTS)
FROM HumanResources.Employee AS Employee
WHERE EmployeeID = 168
FOR XML AUTO;
Notice that the subquery includes a FOR XML clause that uses AUTO mode and includes the ELEMENTS option. The FOR XML clause also includes the TYPE option, which specifies that the data returned by the subquery be returned as the XML type. You must include the TYPE option to preserve the data as XML in the outer SELECT statement.(SELECT FirstName, LastName
FROM Person.Contact AS EmployeeName
WHERE EmployeeName.ContactID = Employee.ContactID
FOR XML AUTO, TYPE, ELEMENTS)
FROM HumanResources.Employee AS Employee
WHERE EmployeeID = 168
FOR XML AUTO;
The outer SELECT statement also includes a FOR XML clause, but the ELEMENTS option is not included. As a result, only the first and last names will be returned as child elements, but the employee ID and login ID will be returned as attributes, as shown in the following XML:
The EXPLICIT Mode
The EXPLICIT mode provides very specific control over your XML, but this mode is much more complex to use than the RAW or AUTO modes. To use this mode, you must build your SELECT statements in such as way as to define the XML hierarchy and structure. In addition, you must create a SELECT statement for each level of that hierarchy and use UNION ALL clauses to join those statements.There are a number of rules that describe how to define your SELECT statements when using the EXPLICIT mode, and it is beyond the scope of this article to review all those rules, so be sure to refer to the topic “Using EXPLICIT Mode” in SQL Server Books Online for the details about how to construct your SELECT statements. In the meantime, let’s take a look at a few examples that help demonstrate some of the basic elements of the EXPLICIT mode.
When constructing your SELECT statement, you must include two columns in your SELECT list that describe the XML hierarchy. The first column, Tag, is assigned a numerical value for each level of the hierarchy. For instance, the first SELECT statement should include a Tag column with a value of 1. This is the top level of the hierarchy. The second SELECT statement should include a Tag column with a value of 2, and so on.
The second column that you should include in your SELECT statement is Parent. Again, this is a numerical value that identifies the parent of the hierarchy based on the Tag values you’ve assigned. In the first SELECT statement, the Parent value should be null to indicate that this is a top level hierarchy.
Your first SELECT statement should also include a reference to all the columns that will make up the XML structure. The columns must also include aliases that define that structure. Let’s look at an example to help understand how this all works. The following SELECT statements return results similar to what you’ve seen in previous examples; however, the SELECT statements themselves are more detailed:
SELECT 1 AS Tag,
NULL AS Parent,
e.EmployeeID AS [Employee!1!EmployeeID],
NULL AS [ContactInfo!2!FirstName!ELEMENT],
NULL AS [ContactInfo!2!MiddleName!ELEMENT],
NULL AS [ContactInfo!2!LastName!ELEMENT]
FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
UNION ALL
SELECT 2 AS Tag,
1 AS Parent,
e.EmployeeID,
c.FirstName,
c.MiddleName,
c.LastName
FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON e.ContactID = c.ContactID
WHERE c.FirstName = 'Rob'
ORDER BY [Employee!1!EmployeeID], [ContactInfo!2!FirstName!ELEMENT]
FOR XML EXPLICIT;
In the first SELECT statement, I
begin by defining the Tag column and assigning a value of 1 to that
column. Next I define the Parent column and assign a null value. I then
define the EmployeeID column and assign an alias to that column. Notice that I use a very specific structure to define the alias name:NULL AS Parent,
e.EmployeeID AS [Employee!1!EmployeeID],
NULL AS [ContactInfo!2!FirstName!ELEMENT],
NULL AS [ContactInfo!2!MiddleName!ELEMENT],
NULL AS [ContactInfo!2!LastName!ELEMENT]
FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
UNION ALL
SELECT 2 AS Tag,
1 AS Parent,
e.EmployeeID,
c.FirstName,
c.MiddleName,
c.LastName
FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON e.ContactID = c.ContactID
WHERE c.FirstName = 'Rob'
ORDER BY [Employee!1!EmployeeID], [ContactInfo!2!FirstName!ELEMENT]
FOR XML EXPLICIT;
: The name of the element that the value should be assigned to. : The tag number associated with the hierarchy that the value should be assigned to, as defined in the Tag column. : The name of the attribute associated with the column value, unless an optional directive is specified. For example, if the ELEMENT directive is specified, : Additional information for how to construct the XML.
Because the next three columns in the SELECT list are associated with the second level of the XML hierarchy, which is defined in the second SELECT statement, null values are assigned to the alias names for the column. This will provide the XML structure necessary to join the two SELECT statements.
The second SELECT statement is much simpler, but it still includes the Tag and Parent columns in the SELECT list. The remaining columns in the SELECT list are defined as you would normally define columns in your query.
The result set for the two SELECT statements is then ordered by the EmployeeID and FirstName columns. This is necessary so that null values appear first in the result set to ensure that the XML is properly formatted. The FOR XML clause is then appended to the end of the SELECT statement in order to generate the following XML:
SELECT 1 AS Tag,
NULL AS Parent,
e.EmployeeID AS [Employee!1!EmployeeID!ELEMENT],
NULL AS [ContactInfo!2!FirstName!ELEMENT],
NULL AS [ContactInfo!2!MiddleName!ELEMENT],
NULL AS [ContactInfo!2!LastName!ELEMENT]
FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
UNION ALL
SELECT 2 AS Tag,
1 AS Parent,
e.EmployeeID,
c.FirstName,
c.MiddleName,
c.LastName
FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON e.ContactID = c.ContactID
WHERE c.FirstName = 'Rob'
ORDER BY [Employee!1!EmployeeID!ELEMENT], [ContactInfo!2!FirstName!ELEMENT]
FOR XML EXPLICIT;
Now the EmployeeID value will be displayed as a child element of NULL AS Parent,
e.EmployeeID AS [Employee!1!EmployeeID!ELEMENT],
NULL AS [ContactInfo!2!FirstName!ELEMENT],
NULL AS [ContactInfo!2!MiddleName!ELEMENT],
NULL AS [ContactInfo!2!LastName!ELEMENT]
FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
UNION ALL
SELECT 2 AS Tag,
1 AS Parent,
e.EmployeeID,
c.FirstName,
c.MiddleName,
c.LastName
FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON e.ContactID = c.ContactID
WHERE c.FirstName = 'Rob'
ORDER BY [Employee!1!EmployeeID!ELEMENT], [ContactInfo!2!FirstName!ELEMENT]
FOR XML EXPLICIT;
SELECT 1 AS Tag,
NULL AS Parent,
e.EmployeeID AS [Employee!1!EmployeeID!ELEMENT],
NULL AS [ContactInfo!2!FirstName!ELEMENT],
NULL AS [ContactInfo!2!MiddleName!ELEMENTXSINIL],
NULL AS [ContactInfo!2!LastName!ELEMENT]
FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
UNION ALL
SELECT 2 AS Tag,
1 AS Parent,
e.EmployeeID,
c.FirstName,
c.MiddleName,
c.LastName
FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON e.ContactID = c.ContactID
WHERE c.FirstName = 'Rob'
ORDER BY [Employee!1!EmployeeID!ELEMENT], [ContactInfo!2!FirstName!ELEMENT]
FOR XML EXPLICIT;
Now the results will include the xsi:nil attribute where values are null in the MiddleName column, as shown in the following XML:NULL AS Parent,
e.EmployeeID AS [Employee!1!EmployeeID!ELEMENT],
NULL AS [ContactInfo!2!FirstName!ELEMENT],
NULL AS [ContactInfo!2!MiddleName!ELEMENTXSINIL],
NULL AS [ContactInfo!2!LastName!ELEMENT]
FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
UNION ALL
SELECT 2 AS Tag,
1 AS Parent,
e.EmployeeID,
c.FirstName,
c.MiddleName,
c.LastName
FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON e.ContactID = c.ContactID
WHERE c.FirstName = 'Rob'
ORDER BY [Employee!1!EmployeeID!ELEMENT], [ContactInfo!2!FirstName!ELEMENT]
FOR XML EXPLICIT;
The PATH Mode
When you specify the PATH mode in the FOR XML clause, column names (or their aliases) are treated as XPath expressions that determine how the data values will be mapped to the XML result set. By default, XML elements are defined based on column names. You can modify the default behavior by using the at (@) symbol to define attributes or the forward slash (/) to define the hierarchy. Let’s take a look at a few examples to demonstrate how all this works.We’ll begin with the PATH mode’s default behavior. The following example includes a FOR XML clause that specifies only the PATH option:
SELECT e.EmployeeID, c.FirstName,
c.MiddleName, c.LastName
FROM HumanResources.Employee AS e
INNER JOIN Person.Contact AS c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML PATH;
Because no specific attributes or hierarchies have been defined, the query will return the following XML:c.MiddleName, c.LastName
FROM HumanResources.Employee AS e
INNER JOIN Person.Contact AS c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML PATH;
You can also rename the row element and define a root element, as you’ve seen in earlier examples:
SELECT e.EmployeeID, c.FirstName,
c.MiddleName, c.LastName
FROM HumanResources.Employee AS e
INNER JOIN Person.Contact AS c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML PATH ('Employee'), ROOT ('Employees');
As the following results show, the XML now includes the c.MiddleName, c.LastName
FROM HumanResources.Employee AS e
INNER JOIN Person.Contact AS c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML PATH ('Employee'), ROOT ('Employees');
SELECT e.EmployeeID AS "@EmpID",
c.FirstName, c.MiddleName, c.LastName
FROM HumanResources.Employee AS e
INNER JOIN Person.Contact AS c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML PATH ('Employee'), ROOT ('Employees');
Now the c.FirstName, c.MiddleName, c.LastName
FROM HumanResources.Employee AS e
INNER JOIN Person.Contact AS c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML PATH ('Employee'), ROOT ('Employees');
SELECT e.EmployeeID AS "@EmpID",
c.FirstName, c.MiddleName, c.LastName
FROM HumanResources.Employee AS e
INNER JOIN Person.Contact AS c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML PATH ('Employee'), ROOT ('Employees'), ELEMENTS XSINIL;
Now your results include the xsi:nil attribute for those fields that contain null values:c.FirstName, c.MiddleName, c.LastName
FROM HumanResources.Employee AS e
INNER JOIN Person.Contact AS c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML PATH ('Employee'), ROOT ('Employees'), ELEMENTS XSINIL;
Note: Because the PATH mode automatically returns values as individual child elements, the ELEMENTS directive has no effect when used by itself in a FOR XML clause. It is only when the XSINIL option is also specified that the ELEMENTS directive adds value to the clause.
SELECT e.EmployeeID AS "@EmpID",
c.FirstName AS "EmployeeName/FirstName",
c.MiddleName AS "EmployeeName/MiddleName",
c.LastName AS "EmployeeName/LastName"
FROM HumanResources.Employee AS e
INNER JOIN Person.Contact AS c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML PATH ('Employee'), ROOT ('Employees'), ELEMENTS XSINIL;
The statement returns the following XML result set:c.FirstName AS "EmployeeName/FirstName",
c.MiddleName AS "EmployeeName/MiddleName",
c.LastName AS "EmployeeName/LastName"
FROM HumanResources.Employee AS e
INNER JOIN Person.Contact AS c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML PATH ('Employee'), ROOT ('Employees'), ELEMENTS XSINIL;
Suppose that you now want to add an email address to your result set. You can simply add the column to the SELECT list after the other columns, as shown in the following example:
SELECT e.EmployeeID AS "@EmpID",
c.FirstName AS "EmployeeName/FirstName",
c.MiddleName AS "EmployeeName/MiddleName",
c.LastName AS "EmployeeName/LastName",
c.EmailAddress
FROM HumanResources.Employee AS e
INNER JOIN Person.Contact AS c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML PATH ('Employee'), ROOT ('Employees'), ELEMENTS XSINIL;
Because the column name is EmailAddress and no alias has been defined on that column, your XML results will now include the c.FirstName AS "EmployeeName/FirstName",
c.MiddleName AS "EmployeeName/MiddleName",
c.LastName AS "EmployeeName/LastName",
c.EmailAddress
FROM HumanResources.Employee AS e
INNER JOIN Person.Contact AS c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML PATH ('Employee'), ROOT ('Employees'), ELEMENTS XSINIL;
SELECT e.EmployeeID AS "@EmpID",
c.FirstName AS "EmployeeName/FirstName",
c.MiddleName AS "EmployeeName/MiddleName",
c.EmailAddress,
c.LastName AS "EmployeeName/LastName"
FROM HumanResources.Employee AS e
INNER JOIN Person.Contact AS c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML PATH ('Employee'), ROOT ('Employees'), ELEMENTS XSINIL;
Because I do not list the parts of the employee names consecutively, they are separated in the XML results:c.FirstName AS "EmployeeName/FirstName",
c.MiddleName AS "EmployeeName/MiddleName",
c.EmailAddress,
c.LastName AS "EmployeeName/LastName"
FROM HumanResources.Employee AS e
INNER JOIN Person.Contact AS c
ON c.ContactID = e.ContactID
WHERE c.FirstName = 'Rob'
FOR XML PATH ('Employee'), ROOT ('Employees'), ELEMENTS XSINIL;
In an earlier example, I demonstrated how to include an XML column in your query. You can also include an XML column when using the PATH mode. The XML data returned by the column is incorporated into the XML that is returned by the query. For instance, the following SELECT statement adds education data to the result set:
SELECT e.EmployeeID AS "@EmpID",
c.FirstName AS "EmployeeName/FirstName",
c.MiddleName AS "EmployeeName/MiddleName",
c.LastName AS "EmployeeName/LastName",
c.EmailAddress,
jc.Resume.query('declare namespace ns=
"http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
/ns:Resume/ns:Education')
FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON c.ContactID = e.ContactID
INNER JOIN HumanResources.JobCandidate jc
ON e.EmployeeID = jc.EmployeeID
WHERE e.EmployeeID = 268
FOR XML PATH ('Employee');
The c.FirstName AS "EmployeeName/FirstName",
c.MiddleName AS "EmployeeName/MiddleName",
c.LastName AS "EmployeeName/LastName",
c.EmailAddress,
jc.Resume.query('declare namespace ns=
"http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume";
/ns:Resume/ns:Education')
FROM HumanResources.Employee e INNER JOIN Person.Contact c
ON c.ContactID = e.ContactID
INNER JOIN HumanResources.JobCandidate jc
ON e.EmployeeID = jc.EmployeeID
WHERE e.EmployeeID = 268
FOR XML PATH ('Employee');
No comments:
Post a Comment