2014-10-06 5 views
3

Я довольно новичок в FOR XML на SQL Server, я искал значительную информацию и не могу найти ответ на этот вопрос.FOR XML SQL Server - переменное имя элемента в выводе XML

Могу ли я иметь имя переменной с использованием «для xml», где имя элемента не жестко закодировано и вместо этого берется из ячейки в каждой строке? Рассмотрим следующий пример ...

Таблица ORDERS:

ID  STATUS  TIME  AMOUNT 
------------------------------------ 
1  COMPLETE  02:31  2355 
2  ACCEPTED  02:39  6653 
3  ACCEPTED  04:21  4102 
4  RECEIVED  05:03  4225 

FOR XML запрос:

select ID, 
     TIME as STATUS_TIME, 
     AMOUNT as CURRENT_AMOUNT 
from ORDERS 
for xml raw(' **STATUS NAME HERE** '),root('ORDERS'), elements 

Требуемая мощность:

<ORDERS> 
    <COMPLETE>    <<<<--- Variable element name from STATUS in ORDERS 
     <ID>1</ID> 
     <STATUS_TIME>02:31</STATUS_TIME> 
     <CURRENT_AMOUNT>2355</CURRENT_AMOUNT> 
    </COMPLETE> 
    <ACCEPTED>    <<<<--- Variable element name from STATUS in ORDERS 
     <ID>2</ID> 
     <STATUS_TIME>02:39</STATUS_TIME> 
     <CURRENT_AMOUNT>6653</CURRENT_AMOUNT> 
    </ACCEPTED> 
    <ACCEPTED>    <<<<--- Variable element name from STATUS in ORDERS 
     <ID>3</ID> 
     <STATUS_TIME>04:21</STATUS_TIME> 
     <CURRENT_AMOUNT>4102</CURRENT_AMOUNT> 
    </ACCEPTED> 
    <RECEIVED>    <<<<--- Variable element name from STATUS in ORDERS 
     <ID>4</ID> 
     <STATUS_TIME>05:03</STATUS_TIME> 
     <CURRENT_AMOUNT>4225</CURRENT_AMOUNT> 
    </RECEIVED> 
</ORDERS> 

Я знаю, что я в состоянии дать атрибуты к именам элементов, и что я мог бы дать индивидууму ORDER в ORDERS и атрибут STATUS, как показано ниже, но, к сожалению, это не то, что люди, которые будут принимать документ XML ищут :(

select ID, 
     STATUS as '@STATUS' 
     TIME as STATUS_TIME, 
     AMOUNT as CURRENT_AMOUNT 
from ORDERS 
for xml raw('ORDER'),root('ORDERS'), elements 

Выход:

<ORDERS> 
    <ORDER STATUS='COMPLETE'>    <<<<--- Attribute for STATUS but not what I want 
     <ID>1</ID> 
     <STATUS_TIME>02:31</STATUS_TIME> 
     <CURRENT_AMOUNT>2355</CURRENT_AMOUNT> 
    </ORDER> 
    <ORDER STATUS='ACCEPTED'>    <<<<--- Attribute for STATUS but not what I want 
     <ID>2</ID> 
     <STATUS_TIME>02:39</STATUS_TIME> 
     <CURRENT_AMOUNT>6653</CURRENT_AMOUNT> 
    </ORDER> 
.... 

Я хотел бы быть в состоянии делать все это в SQL Server, если это возможно. Многие, большое спасибо, если вы можете мне вообще помочь.

+0

Проверьте ответ ... –

ответ

1

Вы не можете указать значение столбца в XML Raw(). Так что вам нужно сделать, это выбрать требуемый столбец из запроса на выборку и результат отлитого в XML, как это -

Схема

DECLARE @temp table (ID int, [STATUS] [varchar](100) NOT NULL, [TIME] [varchar](100), AMOUNT int); 

INSERT @temp (ID, [STATUS], [TIME], AMOUNT) VALUES (1, 'COMPLETE', '02:31', 2355),(2, 'ACCEPTED', '02:41', 6653),(3, 'ACCEPTED', '02:31', 4102),(4, 'ACCEPTED', '02:31', 4225) 

Запрос

SELECT 
CAST('<' + STATUS + '>' + 
    '<ID>' + CAST(ID AS varchar) + '</ID>' + 
    '<TIME>' + TIME + '</TIME>' + 
    '<AMOUNT>' + CAST(AMOUNT AS varchar) + '</AMOUNT>' + 
'</' + STATUS + '>' AS XML) from @temp 
FOR XML PATH(''),root('ORDERS') 

Выход

<ORDERS> 
    <COMPLETE> 
    <ID>1</ID> 
    <TIME>02:31</TIME> 
    <AMOUNT>2355</AMOUNT> 
    </COMPLETE> 
    <ACCEPTED> 
    <ID>2</ID> 
    <TIME>02:41</TIME> 
    <AMOUNT>6653</AMOUNT> 
    </ACCEPTED> 
    <ACCEPTED> 
    <ID>3</ID> 
    <TIME>02:31</TIME> 
    <AMOUNT>4102</AMOUNT> 
    </ACCEPTED> 
    <ACCEPTED> 
    <ID>4</ID> 
    <TIME>02:31</TIME> 
    <AMOUNT>4225</AMOUNT> 
    </ACCEPTED> 
</ORDERS> 
1

В SQL Server схема XML должна быть статической, поэтому невозможно указать имя элемента переменной (будь то документ или атрибут).

Если возможные варианты STATUS полей ограничены и стабильные, вы можете упомянуть их все явно, как в примере ниже:

select (
    select t.ID, t.TIME as [STATUS_TIME], t.AMOUNT as [CURRENT_AMOUNT] 
    from @temp t 
    where t.STATUS = 'ACCEPTED' 
    for xml path('ACCEPTED'), type, elements 
    ), (
    select t.ID, t.TIME as [STATUS_TIME], t.AMOUNT as [CURRENT_AMOUNT] 
    from @temp t 
    where t.STATUS = 'COMPLETE' 
    for xml path('COMPLETE'), type, elements 
    ) 
for xml path('ORDERS'), type; 

Я думаю, вы уже обратили внимание на многочисленные возможности, как этот код может предать вы, но, откровенно говоря, этот подход является единственным доступным, который не включает в себя строковые манипуляции (они будут пагубными для производительности, если размер XML-вывода будет не менее нескольких Mb).

В качестве возможного обходного пути вы можете генерировать этот запрос динамически, в том числе столько разделов, сколько в вашей таблице значений разных значений STATUS. Очень уродливо, но это сработает.