A maneira mais simples de explicar é ver como
FOR XML PATH
funciona para XML real. Imagine uma tabela simples Employee
:EmployeeID Name
1 John Smith
2 Jane Doe
Você poderia usar
SELECT EmployeeID, Name
FROM emp.Employee
FOR XML PATH ('Employee')
Isso criaria XML da seguinte forma
<Employee>
<EmployeeID>1</EmployeeID>
<Name>John Smith</Name>
</Employee>
<Employee>
<EmployeeID>2</EmployeeID>
<Name>Jane Doe</Name>
</Employee>
Removendo o 'Employee' de
PATH
remove as tags xml externas para que esta consulta:SELECT Name
FROM Employee
FOR XML PATH ('')
Criaria
<Name>John Smith</Name>
<Name>Jane Doe</Name>
O que você está fazendo então não é o ideal, o nome da coluna 'data()' força um erro de sql porque está tentando criar uma tag xml que não é uma tag legal, então o seguinte erro é gerado:
O nome da coluna 'Data()' contém um identificador XML inválido conforme exigido por FOR XML; '('(0x0028) é o primeiro caractere com falha.
A subconsulta correlacionada oculta esse erro e apenas gera o XML sem tags:
SELECT Name AS [Data()]
FROM Employee
FOR XML PATH ('')
cria
John Smith Jane Doe
Você está então substituindo espaços por vírgulas, bastante auto-explicativos ...
Se eu fosse você, adaptaria um pouco a consulta:
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;
Não ter nenhum alias de coluna significa que nenhuma tag xml é criada, e adicionar a vírgula na consulta de seleção significa que quaisquer nomes com espaços não causarão erros,
STUFF
irá remover a primeira vírgula e espaço. ADENDO
Para elaborar sobre o que KM disse em um comentário, como isso parece estar recebendo mais algumas visualizações, a maneira correta de escapar caracteres XML seria usar
.value
do seguinte modo: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;