【问题标题】:How can I convert a column value to a xml element name using SQL and FOR XML如何使用 SQL 和 FOR XML 将列值转换为 xml 元素名称
【发布时间】:2013-04-10 14:22:22
【问题描述】:

MyTable 中有以下表格行:

MessageID EMailAddress      DisplayName RecipientType
1         joe@email.com     Joe         To
1,        Bob@email.com     Max         From
1,        Max@email.com     NULL        To
1,        Secret@email.com  Secret      Bcc

我正在尝试将其转换为如下所示的 XML:

<to>
   <displayName>Joe</displayName>
   <address>joe@email.com</address>
</to>
<from>
   <displayName>Bob</displayName>
   <address>Bob@email.com</address>
</from>
<to>
   <address>Max@email.com</address>
</to>
<bcc>
   <displayName>Secret</displayName>
   <address>Secret@email.com</address>
</bcc>

我很接近,但不知道如何将 RecipientType 转换为其他两列的父元素

SELECT 
a.EmailAddress as address, 
a.DisplayName as displayName
FROM MyTable a
WHERE a.Id = 1
FOR XML PATH('address'), TYPE 

有没有办法让“FOR XML PATH('address')”成为 RecipientType 而不是硬编码的“address”?还是有其他选择?

我也尝试过使用 PIVOT,但似乎没有帮助。

我知道我可以使用动态 SQL,但我试图远离它。

【问题讨论】:

    标签: sql sql-server xml sql-server-2005


    【解决方案1】:
    with data as (
        select * from (
        values (1, 'joe@email.com', 'Joe', 'To', 1),
                (1, 'Bob@email.com', 'Bob', 'From', 2),
                (1, 'Max@email.com', null, 'To', 3),
                (1, 'Secret@email.com', 'Secret', 'Bcc', 4)
        ) t(MessageID, EMailAddress, DisplayName, RecipientType, Ordering)
        where MessageID = 1
    ), pivoted as (
        select *
        from data pivot (max(EmailAddress) for RecipientType in ([To], [From], [Bcc])) t
    )
    select (case when [To] is not null then DisplayName else null end) as 'to/displayName', [To] as 'to/address',
            (case when [From] is not null then DisplayName else null end) as 'from/displayName', [From] as 'from/address',
            (case when [Bcc] is not null then DisplayName else null end) as 'bcc/displayName', [Bcc] as 'bcc/address'
    from pivoted
    order by Ordering
    for xml path('')
    

    【讨论】:

    • 我最终没有使用 Pivot,但这回答了我的问题。谢谢!
    【解决方案2】:

    也许这可以让你开始: 无论如何,我认为您将需要一个元素。

    DECLARE @data XML;
    
    SET @data = 
    
    N'
    <root>
    <to>
       <displayName>Joe</displayName>
       <address>joe@email.com</address>
    </to>
    <from>
       <displayName>Bob</displayName>
       <address>Bob@email.com</address>
    </from>
    <to>
       <address>Max@email.com</address>
    </to>
    <bcc>
       <displayName>Secret</displayName>
       <address>Secret@email.com</address>
    </bcc>
    </root>';
    
    
    
    
    SELECT 
          T.myAlias.value('(.)[1]', 'VARCHAR(32)') AS emailAddress
        , T.myAlias.value('fn:local-name(..)', 'nvarchar(50)') as t
    FROM 
        @data.nodes('//address') AS T(myAlias)
    where
        T.myAlias.value('fn:local-name(..)', 'nvarchar(50)') = 'to'
    ;
    

    结果:

    emailAddress                     t
    -------------------------------- --------------------------------------------------
    joe@email.com                    to
    Max@email.com                    to
    

    SELECT
    
          T.myAlias.value('(.)[1]', 'VARCHAR(32)') AS emailAddress
        , T.myAlias.value('(../displayName)[1]', 'VARCHAR(32)') AS displayName
        , T.myAlias.value('fn:local-name(..)', 'nvarchar(50)') as RecipientType
    FROM 
        @data.nodes('//address') AS T(myAlias)
    
    ;
    
    
    emailAddress                     displayName                      RecipientType
    -------------------------------- -------------------------------- 
    joe@email.com                    Joe                              to
    Bob@email.com                    Bob                              from
    Max@email.com                    NULL                             to
    Secret@email.com                 Secret                           bcc
    

    除了身份之外,什么都有。

    一个问题,Xml Shredding 不完全支持 position()。 :

    http://connect.microsoft.com/SQLServer/feedback/details/383888/fully-support-position-in-xquery

    在这篇文章中也看到了:

    Finding node order in XML document in SQL server

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-04
      • 1970-01-01
      • 1970-01-01
      • 2015-09-19
      相关资源
      最近更新 更多