2014-10-06 122 views
3

我很相当新,在SQL Server中FOR XML,我搜索了相当多,我找不到答案。对于XML SQL Server - 输出XML中的变量元素名称

我可以使用'for 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> 

我知道我能给予的属性到元素名称,我可以给个人ORDERORDERSSTATUS像下面属性,但不幸的是,这不是什么将接收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

检查答案... – 2014-10-06 12:43:00

回答

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值。非常丑,但它会起作用。