Najprostszym sposobem wyjaśnienia tego jest przyjrzenie się, jak FOR XML PATH
działa dla rzeczywistego XML. Wyobraź sobie prostą tabelę Employee
:
EmployeeID Name
1 John Smith
2 Jane Doe
Możesz użyć
SELECT EmployeeID, Name
FROM emp.Employee
FOR XML PATH ('Employee')
Spowoduje to utworzenie XML w następujący sposób
<Employee>
<EmployeeID>1</EmployeeID>
<Name>John Smith</Name>
</Employee>
<Employee>
<EmployeeID>2</EmployeeID>
<Name>Jane Doe</Name>
</Employee>
Usuwanie „Pracownika” z PATH
usuwa zewnętrzne znaczniki XML, więc to zapytanie:
SELECT Name
FROM Employee
FOR XML PATH ('')
Utworzyłby
<Name>John Smith</Name>
<Name>Jane Doe</Name>
To, co wtedy robisz, nie jest idealne, nazwa kolumny „data()” wymusza błąd sql, ponieważ próbuje utworzyć znacznik xml, który nie jest prawidłowym znacznikiem, więc generowany jest następujący błąd:
Nazwa kolumny „Data()” zawiera nieprawidłowy identyfikator XML wymagany przez FOR XML; '('(0x0028) to pierwszy znak błędu.
Skorelowane podzapytanie ukrywa ten błąd i po prostu generuje kod XML bez tagów:
SELECT Name AS [Data()]
FROM Employee
FOR XML PATH ('')
tworzy
John Smith Jane Doe
Następnie zastępujesz spacje przecinkami, co jest dość oczywiste...
Na Twoim miejscu nieznacznie dostosowałbym zapytanie:
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;
Brak aliasu kolumny oznacza, że nie są tworzone żadne znaczniki xml, a dodanie przecinka w zapytaniu wybierającym oznacza, że nazwy zawierające spacje nie spowodują błędów,STUFF
usunie pierwszy przecinek i spację.
UZUPEŁNIENIE
Aby rozwinąć to, co KM powiedział w komentarzu, ponieważ wydaje się, że uzyskuje się kilka dodatkowych widoków, prawidłowym sposobem ucieczki znaków XML byłoby użycie .value
w następujący sposób:
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;