What this query does to create comma delimited list SQL Server?
sql, sql-server, sql-server-2008
Solution
The simplest way of explaining it is to look at how `FOR XML PATH` works for actual XML. Imagine a simple table `Employee`:
EmployeeID Name
1 John Smith
2 Jane Doe
You could use
SELECT EmployeeID, Name
FROM emp.Employee
FOR XML PATH ('Employee')
This would create XML as follows
<Employee>
<EmployeeID>1</EmployeeID>
<Name>John Smith</Name>
</Employee>
<Employee>
<EmployeeID>2</EmployeeID>
<Name>Jane Doe</Name>
</Employee>
Removing the 'Employee' from `PATH` removes the outer xml tags so this query:
SELECT Name
FROM Employee
FOR XML PATH ('')
Would create
<Name>John Smith</Name>
<Name>Jane Doe</Name>
What you are then doing is not ideal, the column name 'data()' forces an sql error because it is trying to create an xml tag which is not a legal tag, so the following error is generated:
Column name 'Data()' contains an invalid XML identifier as required by FOR XML; '('(0x0028) is the first character at fault.
The correlated subquery hides this error and just generates the XML with no tags:
SELECT Name AS [Data()]
FROM Employee
FOR XML PATH ('')
creates
John Smith Jane Doe
You are then replacing spaces with commas, fairly self explanatory...
If I were you I would adapt the query slightly:
SELECT E1.deptno,
STUFF(( SELECT ', ' + E2.ename
FROM emp AS e2
WHERE e1.deptno = e2.DEPTNO
FOR XML PATH('')
), 1, 2, '')
FROM EMP AS e1
GROUP BY DEPTNO;
Having no column alias will mean no xml tags are created, and adding the comma within the select query means any names with spaces in will not cause errors,`STUFF` will remove the first comma and space.
ADDENDUM
To elaborate on what KM has said in a comment, as this seems to be getting a few more views, the correct way to escape XML characters would be to use `.value` as follows:
SELECT E1.deptno,
STUFF(( SELECT ', ' + E2.ename
FROM emp AS e2
WHERE e1.deptno = e2.DEPTNO
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 2, '')
FROM EMP AS e1
GROUP BY DEPTNO;
Problem
I've written this query with the help of google to create a delimited list from a table but I didn't understand anything from this query. Can anyone explain me what's happening ``` SELECT E1.deptno, allemp = Replace ((SELECT E2.ename AS 'data()' FROM emp AS e2 WHERE e1.deptno = e2.DEPTNO FOR xml PATH('')), ' ', ', ') FROM EMP AS e1 GROUP BY DEPTNO; ``` Gives me result ``` 10 CLARK, KING, MILLER 20 SMITH, JONES, SCOTT, ADAMS, FORD 30 ALLEN, WARD, MARTIN, BLAKE, TURNER, JAMES ```