2015-05-16 71 views
7

请参阅下面的DDL:为什么STUFF删除XML?

create table #Test (id int,Name varchar(30)) 

insert into #Test values (1,'Ian') 
insert into #Test values(1,'Mark') 
insert into #Test values(2,'James') 
insert into #Test values(3,'Karen') 
insert into #Test values(3,'Suzie') 

和下面的SQL:

select * from #Test for xml path('') 

返回:

<id>1</id> 
<Name>Ian</Name> 
<id>1</id> 
<Name>Mark</Name> 
<id>2</id> 
<Name>James</Name> 
<id>3</id> 
<Name>Karen</Name> 
<id>3</id> 
<Name>Suzie</Name> 

这是我所期望的那样。现在看到下面的SQL:

SELECT distinct ID, 
STUFF((select ','+ NAME from #Test as #Test1 where #Test1.id=#Test2.id FOR XML PATH('')),1,1,'') FROM #Test as #Test2 

返回:

1 Ian,Mark 
2 James 
3 Karen,Suzie 

这就是我想要的东西回来。但是,XML元素去哪了?

回答

1

这不是STUFF,这只是为了删除多余的第一个,

的CONCAT删除XML的东西:

','+ NAME 
or 
NAME + '' 

不要问我为什么它的工作就是这样,也许它的地方记录:-)

1

内的XML语句只是用于生产串联结果。对于XML语句添加外:

SELECT distinct ID, 
    STUFF((select ','+ NAME 
      from Test as #Test1 
      where #Test1.id=#Test2.id 
      FOR XML PATH('')),1,1,'') as Names 
FROM Test as #Test2 
FOR XML PATH('') 

输出:

<ID>1</ID><Names>Ian,Mark</Names><ID>2</ID><Names>James</Names><ID>3</ID><Names>Karen,Suzie</Names> 

小提琴http://sqlfiddle.com/#!6/5f254/13

1

你要比较苹果苹果。虽然这是真的,

select * from #Test for xml path('') 

产生的东西,看起来像XML(但技术上是不是因为它没有根元素),这个(你实际上运行的是什么)

select ',' + name from #Test for xml path('') 

没有。在我的机器上,它产生了ff字符串:“,Ian,Mark,James,Karen,Suzie”。从那里,东西函数重击第一个逗号,并获得逗号分隔值列表。

1

为什么STUFF删除XML?

STUFF删除字符串中的第一个逗号,它不负责删除XML元素名称。

FOR XML PATH使用列名创建XML元素名称。当您将两个值连接在一起时','+ NAME生成的列没有名称,因此FOR XML PATH无法为您生成元素名称。

行为记录在Columns without a Name

任何没有名字的列都会被内联。例如,计算出的 列或嵌套标量查询不指定列别名将 生成没有任何名称的列。

+0

这是我读过的最重要的事情之一。这证明代码实际上是一种黑客攻击,可能在未来的版本中不可靠。这是正确的答案。 – Paul