La façon la plus simple de l'expliquer est de regarder comment FOR XML PATH
fonctionne pour XML réel. Imaginez un simple tableau Employee
:
EmployeeID Name
1 John Smith
2 Jane Doe
Vous pouvez utiliser
SELECT EmployeeID, Name
FROM emp.Employee
FOR XML PATH ('Employee')
Cela créerait XML comme suit
<Employee>
<EmployeeID>1</EmployeeID>
<Name>John Smith</Name>
</Employee>
<Employee>
<EmployeeID>2</EmployeeID>
<Name>Jane Doe</Name>
</Employee>
Suppression de 'Employee' de PATH
supprime les balises xml externes donc cette requête :
SELECT Name
FROM Employee
FOR XML PATH ('')
créerait
<Name>John Smith</Name>
<Name>Jane Doe</Name>
Ce que vous faites alors n'est pas idéal, le nom de la colonne 'data()' force une erreur sql car il essaie de créer une balise xml qui n'est pas une balise légale, donc l'erreur suivante est générée :
Le nom de colonne 'Data()' contient un identifiant XML non valide, comme requis par FOR XML ; '('(0x0028) est le premier caractère fautif.
La sous-requête corrélée masque cette erreur et génère simplement le XML sans balise :
SELECT Name AS [Data()]
FROM Employee
FOR XML PATH ('')
crée
John Smith Jane Doe
Vous remplacez alors les espaces par des virgules, assez explicites...
Si j'étais vous, j'adapterais légèrement la requête :
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;
L'absence d'alias de colonne signifie qu'aucune balise xml n'est créée, et l'ajout de la virgule dans la requête de sélection signifie que tous les noms contenant des espaces ne provoqueront pas d'erreurs,STUFF
supprimera la première virgule et l'espace.
ADDENDA
Pour développer ce que KM a dit dans un commentaire, car cela semble obtenir quelques vues supplémentaires, la bonne façon d'échapper aux caractères XML serait d'utiliser .value
comme suit :
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;