Sql server FOR XML SQL Server-输出XML中的变量元素名称

Sql server FOR XML SQL Server-输出XML中的变量元素名称,sql-server,xml,for-xml,for-xml-path,select-for-xml,Sql Server,Xml,For Xml,For Xml Path,Select For Xml,我对SQL Server中的XML非常陌生,我已经搜索了相当多的内容,但找不到答案 如果元素名不是硬编码的,而是从每行的一个单元格中获取的,那么我可以使用“for xml”来获得一个变量元素名吗?以下面的例子 表订单: ID STATUS TIME AMOUNT ------------------------------------ 1 COMPLETE 02:31 2355 2 ACCEPTED 02:39 6

我对SQL Server中的XML非常陌生,我已经搜索了相当多的内容,但找不到答案

如果元素名不是硬编码的,而是从每行的一个单元格中获取的,那么我可以使用“for xml”来获得一个变量元素名吗?以下面的例子

订单

ID     STATUS       TIME      AMOUNT
------------------------------------
1      COMPLETE     02:31     2355
2      ACCEPTED     02:39     6653
3      ACCEPTED     04:21     4102
4      RECEIVED     05:03     4225
用于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>
输出:

<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>
....


不能在
xmlraw()中指定列值。所以,您需要做的是从select查询中选择必需的列,并将结果转换为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')
选择
铸造(“”+
''+CAST(ID为varchar)+''+
''+时间'''+
''+CAST(金额为varchar)+''+
@temp中的“”作为XML)
对于XML路径(“”),根('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.
02:31
2355
2.
02:41
6653
3.
02:31
4102
4.
02:31
4225

在SQL Server中,XML模式必须是静态的,因此无法指定变量元素名称(文档或属性)

如果
状态
字段的可能选项有限且稳定,则可以明确提及所有选项,如下例所示:

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
值所包含的尽可能多的部分。非常难看,但它会起作用

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;