Nejjednodušším způsobem, jak to vysvětlit, je podívat se na to, jak FOR XML PATH
funguje pro skutečné XML. Představte si jednoduchou tabulku Employee
:
EmployeeID Name
1 John Smith
2 Jane Doe
Můžete použít
SELECT EmployeeID, Name
FROM emp.Employee
FOR XML PATH ('Employee')
To by vytvořilo XML následovně
<Employee>
<EmployeeID>1</EmployeeID>
<Name>John Smith</Name>
</Employee>
<Employee>
<EmployeeID>2</EmployeeID>
<Name>Jane Doe</Name>
</Employee>
Odebrání 'Zaměstnanec' z PATH
odebere vnější xml tagy, takže tento dotaz:
SELECT Name
FROM Employee
FOR XML PATH ('')
By vytvořil
<Name>John Smith</Name>
<Name>Jane Doe</Name>
To, co potom děláte, není ideální, název sloupce 'data()' vynutí chybu SQL, protože se pokouší vytvořit značku xml, která není legální značkou, takže se vygeneruje následující chyba:
Název sloupce 'Data()' obsahuje neplatný identifikátor XML, jak vyžaduje FOR XML; '('(0x0028) je první chybný znak.
Korelovaný poddotaz tuto chybu skryje a pouze vygeneruje XML bez značek:
SELECT Name AS [Data()]
FROM Employee
FOR XML PATH ('')
vytváří
John Smith Jane Doe
Potom nahrazujete mezery čárkami, což je docela samovysvětlující...
Na vašem místě bych dotaz mírně upravil:
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;
Bez aliasu sloupce nebudou vytvořeny žádné xml tagy a přidání čárky do výběrového dotazu znamená, že jakákoli jména s mezerami nezpůsobí chyby,STUFF
odstraní první čárku a mezeru.
DODATEK
Chcete-li upřesnit, co KM řekl v komentáři, protože se zdá, že to získává několik dalších zobrazení, správným způsobem, jak uniknout znakům XML, by bylo použít .value
takto:
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;