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

Inner для 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> 

Fiddle http://sqlfiddle.com/#!6/5f254/13

1

Вы должны сравнивать яблоки с яблоками. Хотя это правда, что

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

производит то, что выглядит как XML (но технически это не потому, что он не имеет корневой элемент), это (то, что вы на самом деле работает)

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

не делает. На моей машине он создает строку ff: «, Ян, Марк, Джеймс, Карен, Сьюзи». Оттуда функция stuff запускает первую запятую, и вы получаете список значений, разделенных запятыми.

1

Почему STUFF удаляет XML?

STUFF удаляет первую запятую в строке, не несет ответственности за удаление имен элементов XML.

FOR XML PATH использует имена столбцов для создания имен элементов XML. Когда вы объединяете два значения вместе ','+ NAME, результирующий столбец не имеет имени, поэтому FOR XML PATH не может сгенерировать имя элемента для вас.

Поведение задокументировано в Columns without a Name.

Любая колонка без названия будет встроена. Например, вычисляемые столбцы или вложенные скалярные запросы, которые не указывают псевдоним столбца, будут генерировать столбцы без какого-либо имени.

+0

Это одна из самых важных вещей, которые я прочитал об этом. Это доказывает, что код на самом деле является взломом и, вероятно, в будущих выпусках его нельзя использовать. Это правильный ответ. – Paul

Смежные вопросы