SQL Server FOR XML PATH动态地改变标签

时间:2015-05-11 17:43:44

标签: sql sql-server xml

尝试在SQL 2012中使用FOR XML。需要有这样的结果:

<Loader xmlns:xsi="url1" xmlns="url2">
  <Buy_New>
    <Ticker>IBM</Ticker>
    <Acct>12345</Acct>
    <Qty>10</Qty>
  </Buy_New>
  <Sell_New>
    <Ticker>MSFT</Ticker>
    <Acct>12345</Acct>
    <Qty>15</Qty>
  </Sell_New>
  <Buy_New>
    <Ticker>IBM</Ticker>
    <Acct>12345</Acct>
    <Qty>10</Qty>
  </Buy_New>
</Loader>

在这里查看,MSDN等,我没有看到在我的查询中动态更改<Buy_New><Sell_New>(我有大约20种不同类型可用)的方法,我已经探索过使用FOR XML PATH和FOR XML EXPLICIT,但两者似乎都需要静态元素标记。

有没有办法从查询中的行中驱动标记?

@Jon C当然:这就是我所拥有的:

SELECT
(
    SELECT
    Investment1 as Investment,
    EventDate1 as Date,
    Quantity1 as Quantity
    FROM #temptable e1 where e1.temp_id = e.temp_id
    FOR XML PATH(''),TYPE
) AS 'DYNAMICTAG'
FROM #temptable e
FOR XML PATH(''), ROOT('Loader')`

以下是结果示例。 DYNAMICTAG是需要更改为<Buy_New><Sell_New>等的部分。

<Loader>
  <DYNAMICTAG>
    <Investment>XYZ</Investment>
    <Date>2015-05-08T00:00:00</Date>
    <Quantity>50</Quantity>
  </DYNAMICTAG>
  <DYNAMICTAG>
    <Investment>ABC</Investment>
    <Date>2015-05-08T00:00:00</Date>
    <Quantity>10</Quantity>
  </DYNAMICTAG>
  <DYNAMICTAG>
    <Investment>CSCO</Investment>
    <Date>2015-05-08T00:00:00</Date>
    <Quantity>50</Quantity>
  </DYNAMICTAG>
  <DYNAMICTAG>
    <Investment>IBM</Investment>
    <Date>2015-05-08T00:00:00</Date>
    <Quantity>30</Quantity>
  </DYNAMICTAG>
</Loader>

3 个答案:

答案 0 :(得分:32)

我不确定确定标签是否应该“买新”的条件。或者&#39; sell_new&#39;,但这可能适合您:

    SELECT
(
    SELECT
    Investment1 as Investment,
    EventDate1 as Date,
    Quantity1 as Quantity
    FROM #temptable e1 where e1.temp_id = e.temp_id
    AND (SOME CONDITION FOR 'Buy_New')
    FOR XML PATH('Buy_New'),TYPE
) ,
(
    SELECT
    Investment1 as Investment,
    EventDate1 as Date,
    Quantity1 as Quantity
    FROM #temptable e1 where e1.temp_id = e.temp_id
    AND (SOME CONDITION FOR 'Sell_New')
    FOR XML PATH('Sell_New'),TYPE
)
FROM #temptable e
FOR XML PATH(''), ROOT('Loader')
GO

编辑:

根据你的回答,我知道你需要更有活力的东西。这可能不是您正在寻找的优雅解决方案,但它可以完成工作而无需对每个元素进行硬编码:

首先,创建一个表来存储所需的动态元素名称:

create table elements (id int, name nvarchar(20))

insert into elements (id, name) values (1, 'sell_new')
insert into elements (id, name) values (2, 'buy_new')
insert into elements (id, name) values (3, 'other_new')

然后是解决方法:

SELECT cast('<' + e.name +'>' +
        cast(   
                (
                    SELECT
                    Investment AS 'Investment',
                    EventDate as 'Date',
                    Quantity AS 'Quantity'
                    FROM temptable t1
                    WHERE t1.investment = t.investment
                    FOR XML PATH(''),TYPE
                ) as varchar(max)) 
    + '</' + e.name +'>' as xml)
from temptable t 
JOIN elements e ON e.id = t.RecordType
order by investment
for xml path(''), root('Loader')

结果:

<Loader>
  <sell_new>
    <Investment>abc</Investment>
    <Quantity>456</Quantity>
  </sell_new>
  <buy_new>
    <Investment>cde</Investment>
    <Quantity>789</Quantity>
  </buy_new>
  <sell_new>
    <Investment>efg</Investment>
    <Quantity>0</Quantity>
  </sell_new>
</Loader>

答案 1 :(得分:4)

精选答案(基于@ JonC建议使用CAST,但不需要单独的表来保存标签的所有不同可能性)

SELECT
    (
    SELECT 
        CAST('<' + t1.RecordType + '>' +
            CAST(
            (
                SELECT
                t2.Portfolio1 AS 'Portfolio',
                t2.Qty1 AS 'Qty',
                t2.Price AS 'Price',
                FROM #temptable t2 
                WHERE t2.temptable_id = t1.temptable_id
                FOR XML PATH(''),TYPE
            ) as varchar(max))
        + '</' + t1.RecordType + '>' as xml)
    from #temptable t1
    FOR XML PATH(''), TYPE 
    ) AS 'TranRecords'
FOR XML PATH(''), ROOT('Loader')

答案 2 :(得分:1)

可能有一个更优雅的解决方案(我希望其他人发布它!)但我认为雅各布的博客在这里有一个可行的解决方案:

FOR XML PATH – Yet another shaping example using FOR XML PATH

代码示例在这里:

SELECT
    (
        SELECT
        Investment AS 'Investment',
        Quantity AS 'Quantity',
        Price AS 'Price'
        FROM #temptable
        WHERE RecordType = 'Buy'
        FOR XML PATH('Buy_New'),TYPE
    ) AS 'TransactionRecords',
    (
        SELECT
        Investment AS 'Investment',
        Quantity AS 'Quantity',
        Price AS 'Price'
        FROM #temptable
        WHERE RecordType = 'Sell'
        FOR XML PATH('Sell_New'),TYPE
    ) AS 'TransactionRecords',
    (
        SELECT
        Investment AS 'Investment',
        Quantity AS 'Quantity',
        Price AS 'Price'
        FROM #temptable
        WHERE RecordType = 'Short'
        FOR XML PATH('Short_New'),TYPE
    ) AS 'TransactionRecords',
    (
        SELECT
        Investment AS 'Investment',
        Quantity AS 'Quantity',
        Price AS 'Price'
        FROM #temptable
        WHERE RecordType = 'Cover'
        FOR XML PATH('Cover_New'),TYPE
    ) AS 'TransactionRecords'
    FOR XML PATH(''), ROOT('GenevaLoader')