Det enklaste sättet att förklara det är att titta på hur FOR XML PATH
fungerar för faktisk XML. Föreställ dig en enkel tabell Employee
:
EmployeeID Name
1 John Smith
2 Jane Doe
Du kan använda
SELECT EmployeeID, Name
FROM emp.Employee
FOR XML PATH ('Employee')
Detta skulle skapa XML enligt följande
<Employee>
<EmployeeID>1</EmployeeID>
<Name>John Smith</Name>
</Employee>
<Employee>
<EmployeeID>2</EmployeeID>
<Name>Jane Doe</Name>
</Employee>
Ta bort "Anställd" från PATH
tar bort de yttre xml-taggarna så denna fråga:
SELECT Name
FROM Employee
FOR XML PATH ('')
Skulle skapa
<Name>John Smith</Name>
<Name>Jane Doe</Name>
Det du sedan gör är inte idealiskt, kolumnnamnet 'data()' tvingar fram ett sql-fel eftersom det försöker skapa en xml-tagg som inte är en laglig tagg, så följande fel genereras:
Kolumnnamnet 'Data()' innehåller en ogiltig XML-identifierare som krävs av FOR XML; '('(0x0028) är det första tecknet som är fel.
Den korrelerade underfrågan döljer detta fel och genererar bara XML utan taggar:
SELECT Name AS [Data()]
FROM Employee
FOR XML PATH ('')
skapar
John Smith Jane Doe
Du ersätter då mellanslag med kommatecken, ganska självförklarande...
Om jag var du skulle jag anpassa frågan något:
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;
Att inte ha något kolumnalias kommer att innebära att inga xml-taggar skapas, och att lägga till kommatecken i urvalsfrågan innebär att alla namn med mellanslag inte orsakar fel,STUFF
kommer att ta bort det första kommatecken och mellanslag.
TILLÄGG
För att utveckla vad KM har sagt i en kommentar, eftersom detta verkar få några fler visningar, skulle det korrekta sättet att undvika XML-tecken vara att använda .value
enligt följande:
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;