それを説明する最も簡単な方法は、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()'に、FORXMLで必要な無効な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タグが作成されないことを意味し、selectクエリ内にコンマを追加すると、スペースを含む名前でエラーが発生しないことを意味します。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;