How does the FOR XML PATH ('')
clause do its work when concatenating rows in SQL Server?
I just want an explanation of how the FOR XML PATH ('')
clause works...
A SELECT query returns results as a rowset. You can optionally retrieve formal results of a SQL query as XML by specifying the FOR XML clause in the query. The FOR XML clause can be used in top-level queries and in subqueries. The top-level FOR XML clause can be used only in the SELECT statement.
We can use FOR XML PATH to prepare a comma-separated string from the existing data. Let's create an Authors table and insert a few records into it. In the data, we can see we have an ID column and the AuthorName column. If we just select the records, it gives the output in the following format.
You can concatenate rows into single string using COALESCE method. This COALESCE method can be used in SQL Server version 2008 and higher. All you have to do is, declare a varchar variable and inside the coalesce, concat the variable with comma and the column, then assign the COALESCE to the variable.
The XMLConcat() function concatenates two XML objects (either two elements or two attributes) to produce a single XML object.
What FOR XML PATH('xxx')
does is create an XML string for the resultset that puts each row in a <xxx></xxx>
element and each column value inside the row, in an element with the name for that column.
If the PATH is empty (i.e. PATH('')
) it omits the row element in the XML generation. If the column has no name it omits the column element in the XML generation. When both PATH is empty and columns have no names it effectively becomes a string concatenation of all rows.
Run the following statements to get a better insight in the process:
-- Each row is in a <beta></beta> element
-- Each column in that row in a <alfa></alfa> element (the column name)
SELECT
alfa=','+TABLE_SCHEMA + '.' + TABLE_NAME
FROM
INFORMATION_SCHEMA.TABLES
FOR
XML PATH('beta');
-- Since the PATH is empty, the rows are not put inside an element
-- Each column in that row is in a <alfa></alfa> element (the column name)
SELECT
alfa=','+TABLE_SCHEMA + '.' + TABLE_NAME
FROM
INFORMATION_SCHEMA.TABLES
FOR
XML PATH('');
-- Since the PATH is empty, the rows are not put inside an element
-- Since the column has no name it is not put inside an element
SELECT
','+TABLE_SCHEMA + '.' + TABLE_NAME
FROM
INFORMATION_SCHEMA.TABLES
FOR
XML PATH('');
-- This uses the STUFF function to remove the leading comma to get a proper comma-seperated list
SELECT STUFF((
SELECT
','+TABLE_SCHEMA + '.' + TABLE_NAME
FROM
INFORMATION_SCHEMA.TABLES
FOR
XML PATH('')
),1,1,''
) AS comma_seperated_list;
Now I hear you asking: How can I remove the column name when I simply select a column from a table. There are several ways, in order of my preference:
SELECT [text()]=column_name ...
SELECT (SELECT column_name) ...
SELECT CAST(column_value AS <TYPE of the column>) ...
Examples:
SELECT
[text()]=TABLE_NAME
FROM
INFORMATION_SCHEMA.TABLES
FOR
XML PATH('');
SELECT
(SELECT TABLE_NAME)
FROM
INFORMATION_SCHEMA.TABLES
FOR
XML PATH('');
SELECT
CAST(TABLE_NAME AS SYSNAME)
FROM
INFORMATION_SCHEMA.TABLES
FOR
XML PATH('');
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With