2015-05-16 66 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