Reg*_*ser 12 sql sql-server sql-server-2008
我在google的帮助下编写了这个查询,从表中创建了一个分隔列表,但我对此查询没有任何理解.
任何人都可以解释我发生了什么
SELECT
E1.deptno,
allemp = Replace ((SELECT E2.ename AS 'data()'
FROM emp AS e2
WHERE e1.deptno = e2.DEPTNO
FOR xml PATH('')), ' ', ', ')
FROM EMP AS e1
GROUP BY DEPTNO;
Run Code Online (Sandbox Code Playgroud)
给我结果
10 CLARK, KING, MILLER
20 SMITH, JONES, SCOTT, ADAMS, FORD
30 ALLEN, WARD, MARTIN, BLAKE, TURNER, JAMES
Run Code Online (Sandbox Code Playgroud)
Gar*_*thD 38
解释它的最简单方法是查看FOR XML PATH
实际XML的工作原理.想象一个简单的表格Employee
:
EmployeeID Name
1 John Smith
2 Jane Doe
Run Code Online (Sandbox Code Playgroud)
你可以用
SELECT EmployeeID, Name
FROM emp.Employee
FOR XML PATH ('Employee')
Run Code Online (Sandbox Code Playgroud)
这将创建XML如下
<Employee>
<EmployeeID>1</EmployeeID>
<Name>John Smith</Name>
</Employee>
<Employee>
<EmployeeID>2</EmployeeID>
<Name>Jane Doe</Name>
</Employee>
Run Code Online (Sandbox Code Playgroud)
删除'Employee' PATH
会删除外部xml标记,因此此查询:
SELECT Name
FROM Employee
FOR XML PATH ('')
Run Code Online (Sandbox Code Playgroud)
会创造
<Name>John Smith</Name>
<Name>Jane Doe</Name>
Run Code Online (Sandbox Code Playgroud)
您正在做的事情并不理想,列名'data()'强制sql错误,因为它试图创建一个不合法标记的xml标记,因此会生成以下错误:
列名'Data()'包含FOR XML所需的无效XML标识符; '('(0x0028)是第一个出错的角色.
相关子查询隐藏此错误,只生成没有标记的XML:
SELECT Name AS [Data()]
FROM Employee
FOR XML PATH ('')
Run Code Online (Sandbox Code Playgroud)
创建
John Smith Jane Doe
Run Code Online (Sandbox Code Playgroud)
然后你用逗号替换空格,相当自我解释......
如果我是你,我会略微调整查询:
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;
Run Code Online (Sandbox Code Playgroud)
没有列别名将意味着没有创建xml标记,并且在select查询中添加逗号意味着任何带有空格的名称都不会导致错误,STUFF
将删除第一个逗号和空格.
附录
要详细说明知识管理在评论中所说的内容,因为这似乎可以获得更多的视图,转义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;
Run Code Online (Sandbox Code Playgroud)
从内到外逐步分开.
步骤1:
运行最里面的查询并查看它产生的内容:
SELECT E2.ename AS 'data()'
FROM emp AS e2
WHERE e2.DEPTNO = 10
FOR XML PATH('')
Run Code Online (Sandbox Code Playgroud)
你应该得到一个类似的输出:
CLARK KING MILLER
Run Code Online (Sandbox Code Playgroud)
第2步:
在REPLACE
刚刚替换空间与,
-从而把您的输出入
CLARK, KING, MILLER
Run Code Online (Sandbox Code Playgroud)
第3步:
外部查询获取deptno
值 - 加上内部查询的结果 - 并生成最终结果.
归档时间: |
|
查看次数: |
22914 次 |
最近记录: |