Am einfachsten lässt es sich erklären, wie FOR XML PATH
funktioniert für aktuelles XML. Stellen Sie sich eine einfache Tabelle Employee
vor :
EmployeeID Name
1 John Smith
2 Jane Doe
Sie könnten
verwendenSELECT EmployeeID, Name
FROM emp.Employee
FOR XML PATH ('Employee')
Dies würde XML wie folgt erstellen
<Employee>
<EmployeeID>1</EmployeeID>
<Name>John Smith</Name>
</Employee>
<Employee>
<EmployeeID>2</EmployeeID>
<Name>Jane Doe</Name>
</Employee>
Entfernen des „Employee“ aus PATH
entfernt die äußeren XML-Tags, also diese Abfrage:
SELECT Name
FROM Employee
FOR XML PATH ('')
Würde erstellen
<Name>John Smith</Name>
<Name>Jane Doe</Name>
Was Sie dann tun, ist nicht ideal, der Spaltenname „data()“ erzwingt einen SQL-Fehler, da versucht wird, ein XML-Tag zu erstellen, das kein zulässiges Tag ist, sodass der folgende Fehler generiert wird:
Der Spaltenname 'Data()' enthält einen ungültigen XML-Bezeichner, wie von FOR XML gefordert; '('(0x0028) ist das erste fehlerhafte Zeichen.
Die korrelierte Unterabfrage verbirgt diesen Fehler und generiert nur das XML ohne Tags:
SELECT Name AS [Data()]
FROM Employee
FOR XML PATH ('')
erstellt
John Smith Jane Doe
Sie ersetzen dann Leerzeichen durch Kommas, ziemlich selbsterklärend ...
An deiner Stelle würde ich die Abfrage leicht anpassen:
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;
Wenn kein Spaltenalias vorhanden ist, werden keine XML-Tags erstellt, und das Hinzufügen des Kommas innerhalb der Auswahlabfrage bedeutet, dass alle Namen mit Leerzeichen keine Fehler verursachen,STUFF
entfernt das erste Komma und Leerzeichen.
NACHTRAG
Um näher darauf einzugehen, was KM in einem Kommentar gesagt hat, da dies anscheinend ein paar weitere Aufrufe erhält, wäre der korrekte Weg, XML-Zeichen zu maskieren, die Verwendung von .value
wie folgt:
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;