これを説明する最も簡単な方法は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>
から「従業員」をPATH
削除すると、外側の xml タグが削除されるため、次のクエリは次のようになります。
SELECT Name
FROM Employee
FOR XML PATH ('')
作成します
<Name>John Smith</Name>
<Name>Jane Doe</Name>
次に行っていることは理想的ではありません。列名 'data()' は、正当なタグではない xml タグを作成しようとしているため、SQL エラーを強制するため、次のエラーが生成されます。
列名 'Data()' には、FOR XML で必要な無効な 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;