Ответ 1
Самый простой способ объяснить это - посмотреть, как FOR XML PATH
работает для реального XML. Представьте себе простую таблицу Employee
:
EmployeeID Name
1 John Smith
2 Jane Doe
Вы можете использовать
SELECT EmployeeID, Name
FROM emp.Employee
FOR XML PATH ('Employee')
Это создаст XML следующим образом
<Employee>
<EmployeeID>1</EmployeeID>
<Name>John Smith</Name>
</Employee>
<Employee>
<EmployeeID>2</EmployeeID>
<Name>Jane Doe</Name>
</Employee>
Удаление "Employee" из PATH
удаляет внешние теги xml, чтобы этот запрос:
SELECT Name
FROM Employee
FOR XML PATH ('')
Создал бы
<Name>John Smith</Name>
<Name>Jane Doe</Name>
То, что вы тогда делаете, не является идеальным, имя столбца 'data()' вызывает ошибку sql, потому что он пытается создать тег xml, который не является юридическим тегом, поэтому возникает следующая ошибка:
Название столбца "Данные()" содержит недопустимый XML-идентификатор, как требуется FOR XML; '(' (0x0028) является первым символом при неисправности.
Коррелированный подзапрос скрывает эту ошибку и просто генерирует XML без тегов:
SELECT Name AS [Data()]
FROM Employee
FOR XML PATH ('')
создает
John Smith Jane Doe
Затем вы заменяете пробелы запятыми, достаточно понятными...
Если бы я был вами, я бы немного адаптировал запрос:
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;
Отсутствие псевдонима столбца будет означать, что тэги xml не создаются, а добавление запятой в запросе выбора означает, что любые имена с пробелами не вызовут ошибок, STUFF
удалит первую запятую и пробел.
ДОПОЛНЕНИЕ
Чтобы уточнить, что сказал KM в комментарии, поскольку, похоже, это выглядит как еще несколько просмотров, правильным способом избежать символов XML было бы использовать .value
следующим образом:
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;