2017-02-13 3 views
1

У меня есть таблица только с одним столбцом типа Xml, а также с именем Xml. Каждая строка представляет элемент <recipient>.Окружать все строки в корневом узле Xml (исключая узел имени столбца)

<receipt> 
    <memberid>55555555</memberid> 
    <purchaseid>4408888888859447</purchaseid> 
    <time>2017-02-01</time> 
    <depID>50277</depID> 
    <amount>1398</amount> 
    <theme>Herr</theme> 
    <parentgroup></parentgroup> 
</receipt> 

То, что я хочу сделать, это окружить все эти элементы в одном родительском узле <recipients> таким образом они будут выглядеть примерно так

<recipients> 
    <receipt> 
     <memberid>55555555</memberid> 
     <purchaseid>4408888888859447</purchaseid> 
     <time>2017-02-01</time> 
     <depID>50277</depID> 
     <amount>1398</amount> 
     <theme>Herr</theme> 
     <parentgroup></parentgroup> 
    </receipt> 
    <receipt> 
     <memberid>55555555</memberid> 
     <purchaseid>4408888888859447</purchaseid> 
     <time>2017-02-01</time> 
     <depID>50277</depID> 
     <amount>1398</amount> 
     <theme>Herr</theme> 
     <parentgroup></parentgroup> 
    </receipt> 
    <receipt> 
     <memberid>55555555</memberid> 
     <purchaseid>4408888888859447</purchaseid> 
     <time>2017-02-01</time> 
     <depID>50277</depID> 
     <amount>1398</amount> 
     <theme>Herr</theme> 
     <parentgroup></parentgroup> 
    </receipt> 
</recipients> 

Когда я запускаю запрос как:

SELECT [xml] 
    FROM MyTable 
FOR XML PATH('recipients') 

Я получаю дополнительный <xml> узел для каждой записи, и это то, от чего я пытаюсь избавиться.

ответ

2
Declare @YourTable table (ID int,XML xml) 
Insert Into @YourTable values 
(1,'<receipt><memberid>55555555</memberid><purchaseid>4408888888859447</purchaseid><time>2017-02-01</time><depID>50277</depID> <amount>1398</amount><theme>Herr</theme><parentgroup></parentgroup></receipt>'), 
(2,'<receipt><memberid>66666666</memberid><purchaseid>9999999999999999</purchaseid><time>2017-02-01</time><depID>50277</depID> <amount>1398</amount><theme>Herr</theme><parentgroup></parentgroup></receipt>') 

Select XML AS [*] 
From @YourTable 
For XML Path(''),Root('recipients') 

Возвращает

<recipients> 
    <receipt> 
    <memberid>55555555</memberid> 
    <purchaseid>4408888888859447</purchaseid> 
    <time>2017-02-01</time> 
    <depID>50277</depID> 
    <amount>1398</amount> 
    <theme>Herr</theme> 
    <parentgroup /> 
    </receipt> 
    <receipt> 
    <memberid>66666666</memberid> 
    <purchaseid>9999999999999999</purchaseid> 
    <time>2017-02-01</time> 
    <depID>50277</depID> 
    <amount>1398</amount> 
    <theme>Herr</theme> 
    <parentgroup /> 
    </receipt> 
</recipients> 

EDIT:

Обновлено Ответ благодаря фоновой информации Shnugo в. Как всегда, очень ценится.

+0

Пустые 'Path' и Casting as XML выполнили эту работу. Спасибо! – Disasterkid

+1

@ Disasterkid Счастлив, что это помогло. Я понятия не имею, почему это работает, я случайно наткнулся на это случайно :) –

+0

Привет, я добавил ответ с некоторым объяснением, почему это работает. Нет чуда ... – Shnugo

2

Это не новый ответ, просто какой-то фон.

Этот «трюк» работает, потому что полученный столбец безымянный.

Посмотрите на это:

Declare @Dummy table (SomeValue INT) 
Insert Into @Dummy values(1); 

--Query        --Column's Caption 
---------------------------------------------------------- 
SELECT SomeValue FROM @Dummy;   --SomeValue 
SELECT SomeValue+1-1 FROM @Dummy  --nameless due to the calculation 
SELECT ISNULL(SomeValue,0) FROM @Dummy --nameless due to the function's usage 

Любой вид расчета или использования функции приведет к безымянной колонке. Попробуйте использовать SELECT ... INTO ... FROM или WITH CTE AS (SELECT ...) с столбцом без имени, и вы получите исключение.

В связи с FOR XML PATH это может быть очень важно знать об этом. Если есть имя столбца, движок XML будет использовать его как имя элемента.

Попробуйте это (спасибо Джону за образец кода)

Declare @YourTable table (ID int,XML xml) 
Insert Into @YourTable values 
(1,'<receipt><memberid>55555555</memberid><purchaseid>4408888888859447</purchaseid><time>2017-02-01</time><depID>50277</depID> <amount>1398</amount><theme>Herr</theme><parentgroup></parentgroup></receipt>'), 
(2,'<receipt><memberid>66666666</memberid><purchaseid>9999999999999999</purchaseid><time>2017-02-01</time><depID>50277</depID> <amount>1398</amount><theme>Herr</theme><parentgroup></parentgroup></receipt>') 

ответ Джон работает за счет использования функции

Select cast(XML as xml) 
From @YourTable 
For XML Path(''),Root('recipients') 

Использование AS [*] в качестве псевдонима тоже работает

Select XML AS [*] 
From @YourTable 
For XML Path(''),Root('recipients') 

Лучший способ - официальное голосование - это

Select XML AS [node()] 
From @YourTable 
For XML Path(''),Root('recipients') 

Любая глупая функция или расчет имеет этот эффект

Select ISNULL(XML,XML) 
From @YourTable 
For XML Path(''),Root('recipients') 

Всякий раз, когда люди используют FOR XML PATH Конкатенацией работы вокруг, они используют это, не зная. Типичный SELECT ', ' + SomeColumn приводит к неназванному результату.Без ', ' возник бы «странный» элемент ...

+0

Как обычно, наиболее информативное спасибо за дополнительные усилия и фон +1 –

+0

Спасибо, мистер Шнуго! – Disasterkid