CREATE TABLE #Temp(GroupName VARCHAR(100),FuncationName VARCHAR(100))
GO
INSERT INTO #Temp VALUES('Administrator','View')
INSERT INTO #Temp VALUES('Administrator','Add')
INSERT INTO #Temp VALUES('Administrator','Delete')
INSERT INTO #Temp VALUES('Administrator','Edit')
INSERT INTO #Temp VALUES('Guest','View')
INSERT INTO #Temp VALUES('Guest','Add')
INSERT INTO #Temp VALUES('GG','View')
INSERT INTO #Temp VALUES('Test',NULL)
SELECT FuncationName+',' FROM #Temp FOR XML PATH('')
-- View,Add,Delete,Edit,View,Add,View,
SELECT isnull(FuncationName,'')+',' FROM #Temp FOR XML PATH('')
-- View,Add,Delete,Edit,View,Add,View,,
SELECT FuncationName+',' FROM #Temp WHERE GroupName='Administrator' FOR XML PATH('')
-- View,Add,Delete,Edit,
SELECT GroupName,
( SELECT FuncationName+',' FROM #Temp AS TA WHERE TA.GroupName=TB.GroupName FOR XML PATH('') )
FROM #Temp TB
GROUP BY GroupName
--Administrator View,Add,Delete,Edit,
--GG View,
--Guest View,Add,
--Test
--注:这一步操作一定要用 case 判断, 因为在null值的情况下left函数会出错。
SELECT t.GroupName,CASE LEN(t.FunList) WHEN 0 THEN '' ELSE LEFT(t.FunList,len(t.FunList)-1) END FROM (
SELECT GroupName,
( SELECT FuncationName+',' FROM #Temp AS TA WHERE TA.GroupName=TB.GroupName FOR XML PATH('') ) AS FunList
FROM #Temp TB
GROUP BY GroupName
) AS T
--Administrator View,Add,Delete,Edit
--GG View
--Guest View,Add
--Test
--注:这一步,逗号必须放在最前面,stuff函数只有放在最前面才能准确判断
--此外,与上面不同的是,它会自动过滤掉NULL值的情况,不作处理
Select TB.GroupName,
stuff((select ','+[FuncationName] from #Temp AS TA WHERE TA.GroupName=TB.GroupName for xml path('')),1,1,'') AS FunList
from #Temp TB
GROUP BY TB.GroupName
--Administrator View,Add,Delete,Edit
--GG View
--Guest View,Add
--Test NULL
下面是转载别人的。
——————————————————————————————————————————————
在SQL Server中利用 FOR XML PATH 语句能够把查询的数据生成XML数据,下面是它的一些应用示例。
1
2
3
4
5
|
DECLARE
@TempTable
table
(UserID
int
, UserName nvarchar(50));
insert
into
@TempTable (UserID,UserName)
values
(1,
'a'
)
insert
into
@TempTable (UserID,UserName)
values
(2,
'b'
)
select
UserID,UserName
from
@TempTable
FOR
XML PATH
|
运行这段脚本,将生成如下结果:
1
2
3
4
5
6
7
8
|
<
row
>
<
UserID
>1</
UserID
>
<
UserName
>a</
UserName
>
</
row
>
<
row
>
<
UserID
>2</
UserID
>
<
UserName
>b</
UserName
>
</
row
>
|
1
|
大家可以看到两行数据生成了两个节点,修改一下PATH的参数:
|
1
|
select
UserID,UserName
from
@TempTable
FOR
XML PATH(
'lzy'
)
|
再次运行上述脚本,将生成如下的结果:
1
2
3
4
5
6
7
8
|
<
lzy
>
<
UserID
>1</
UserID
>
<
UserName
>a</
UserName
>
</
lzy
>
<
lzy
>
<
UserID
>2</
UserID
>
<
UserName
>b</
UserName
>
</
lzy
>
|
1
|
可以看到节点变成,其实PATH() 括号内的参数是控制节点名称的,这样的话大家可以看一下如果是空字符串(不是没有参数)会是什么结果?
|
1
|
select
UserID,UserName
from
@TempTable
FOR
XML PATH(
''
)
|
执行上面这段脚本将生成结果:
1
2
3
4
|
<
UserID
>1</
UserID
>
<
UserName
>a</
UserName
>
<
UserID
>2</
UserID
>
<
UserName
>b</
UserName
>
|
这样就不显示上级节点了,大家知道在 PATH 模式中,列名或列别名被作为 XPath 表达式来处理,也就是说,是列的名字,这样大胆试验一下不给指定列名和别名会是怎么样?
1
|
select
CAST
(UserID
AS
varchar
) +
''
,UserName +
''
from
@TempTable
FOR
XML PATH(
''
)
|
运行上面这句将生成结果
1a2b
所有数据都生成一行,而且还没有连接字符,这样的数据可能对大家没有用处,还可以再变化一下:
1
|
select
CAST
(UserID
AS
varchar
) +
','
,UserName +
''
,
';'
from
@TempTable
FOR
XML PATH(
''
)
|
生成结果
1,a;2,b;
大家现在明白了吧,可以通过控制参数来生成自己想要的结果,例如:
1
|
select
'{'
+
CAST
(UserID
AS
varchar
) +
','
,
'"'
+UserName +
'"'
,
'}'
from
@TempTable
FOR
XML PATH(
''
)
|
生成结果
{1,"a"}{2,"b"}
还可以生成其他格式,大家可以根据自己需要的格式进行组合。
下面是一个数据统计的应用,希望大家可以通过下面的实例想到更多的应用
1
2
3
4
5
6
7
8
9
10
11
12
13
|
DECLARE
@T1
table
(UserID
int
, UserName nvarchar(50),CityName nvarchar(50));
insert
into
@T1 (UserID,UserName,CityName)
values
(1,
'a'
,
'上海'
)
insert
into
@T1 (UserID,UserName,CityName)
values
(2,
'b'
,
'北京'
)
insert
into
@T1 (UserID,UserName,CityName)
values
(3,
'c'
,
'上海'
)
insert
into
@T1 (UserID,UserName,CityName)
values
(4,
'd'
,
'北京'
)
insert
into
@T1 (UserID,UserName,CityName)
values
(5,
'e'
,
'上海'
)
SELECT
B.CityName,
LEFT
(UserList,LEN(UserList)-1)
FROM
(
SELECT
CityName,
(
SELECT
UserName+
','
FROM
@T1
WHERE
CityName=A.CityName
FOR
XML PATH(
''
))
AS
UserList
FROM
@T1 A
GROUP
BY
CityName
) B
|
生成结果(每个城市的用户名)
北京 b,d
上海 a,c,e
————————————————————————————————————————————————————————————
FOR XML PATH 有的人可能知道有的人可能不知道,其实它就是将查询结果集以XML形式展现,有了它我们可以简化我们的查询语句实现一些以前可能需要借助函数活存储过程来完成的工作。那么以一个实例为主.
一.FOR XML PATH 简单介绍
那么还是首先来介绍一下FOR XML PATH ,假设现在有一张兴趣爱好表(hobby)用来存放兴趣爱好,表结构如下:
接下来我们来看应用FOR XML PATH的查询结果语句如下:
结果:
< hobbyID > 1 </ hobbyID >
< hName > 爬山 </ hName >
</ row >
< row >
< hobbyID > 2 </ hobbyID >
< hName > 游泳 </ hName >
</ row >
< row >
< hobbyID > 3 </ hobbyID >
< hName > 美食 </ hName >
</ row >
由此可见FOR XML PATH 可以将查询结果根据行输出成XML各式!
那么,如何改变XML行节点的名称呢?代码如下:
结果一定也可想而知了吧?没错原来的行节点<row> 变成了我们在PATH后面括号()中,自定义的名称<MyHobby>,结果如下:
< hobbyID > 1 </ hobbyID >
< hName > 爬山 </ hName >
</ MyHobby >
< MyHobby >
< hobbyID > 2 </ hobbyID >
< hName > 游泳 </ hName >
</ MyHobby >
< MyHobby >
< hobbyID > 3 </ hobbyID >
< hName > 美食 </ hName >
</ MyHobby >
这个时候细心的朋友一定又会问那么列节点如何改变呢?还记的给列起别名的关键字AS吗?对了就是用它!代码如下:
< MyCode > 1 </ MyCode >
< MyName > 爬山 </ MyName >
</ MyHobby >
< MyHobby >
< MyCode > 2 </ MyCode >
< MyName > 游泳 </ MyName >
</ MyHobby >
< MyHobby >
< MyCode > 3 </ MyCode >
< MyName > 美食 </ MyName >
</ MyHobby >
没错我们还可以通过符号+号,来对字符串类型字段的输出格式进行定义。结果如下:
那么其他类型的列怎么自定义? 没关系,我们将它们转换成字符串类型就行啦!例如:
好的 FOR XML PATH就基本介绍到这里吧,更多关于FOR XML的知识请查阅帮助文档!
接下来我们来看一个FOR XML PATH的应用场景吧!那么开始吧。。。。。。
二.一个应用场景与FOR XML PATH应用
首先呢!我们在增加一张学生表,列分别为(stuID,sName,hobby),stuID代表学生编号,sName代表学生姓名,hobby列存学生的爱好!那么现在表结构如下:
这时,我们的要求是查询学生表,显示所有学生的爱好的结果集,代码如下:
SELECT sName,
( SELECT hobby + ' , ' FROM student
WHERE sName = A.sName
FOR XML PATH( '' )) AS StuList
FROM student A
GROUP BY sName
) B
结果如下:
分析: 好的,那么我们来分析一下,首先看这句:
WHERE sName = A.sName
FOR XML PATH( '' )
这句是通过FOR XML PATH 将某一姓名如张三的爱好,显示成格式为:“ 爱好1,爱好2,爱好3,”的格式!
那么接着看:
SELECT sName,
( SELECT hobby + ' , ' FROM student
WHERE sName = A.sName
FOR XML PATH( '' )) AS StuList
FROM student A
GROUP BY sName
) B
剩下的代码首先是将表分组,在执行FOR XML PATH 格式化,这时当还没有执行最外层的SELECT时查询出的结构为:
可以看到StuList列里面的数据都会多出一个逗号,这时随外层的语句:SELECT B.sName,LEFT(StuList,LEN(StuList)-1) as hobby 就是来去掉逗号,并赋予有意义的列名!