2013-04-10 87 views
1

我在MyTable的表行:我如何使用SQL和列值转换为XML元素名称FOR XML

MessageID EMailAddress  DisplayName RecipientType 
1   [email protected]  Joe   To 
1,  [email protected]  Max   From 
1,  [email protected]  NULL  To 
1,  [email protected] Secret  Bcc 

我试图将其转换为XML,看起来像下面这样:

<to> 
    <displayName>Joe</displayName> 
    <address>[email protected]</address> 
</to> 
<from> 
    <displayName>Bob</displayName> 
    <address>[email protected]</address> 
</from> 
<to> 
    <address>[email protected]</address> 
</to> 
<bcc> 
    <displayName>Secret</displayName> 
    <address>[email protected]</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而不是硬编码的'地址'?还是有另一种选择?

我也试过玩过PIVOT,但它似乎没有帮助。

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

回答

1
with data as (
    select * from (
    values (1, '[email protected]', 'Joe', 'To', 1), 
      (1, '[email protected]', 'Bob', 'From', 2), 
      (1, '[email protected]', null, 'To', 3), 
      (1, '[email protected]', '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('') 
+0

我最终没有使用Pivot,但是这回答了我的问题。谢谢! – Jay 2013-04-15 12:10:18

0

也许这可以让你开始: 我认为你将需要一个元素,不管。

DECLARE @data XML; 

SET @data = 

N' 
<root> 
<to> 
    <displayName>Joe</displayName> 
    <address>[email protected]</address> 
</to> 
<from> 
    <displayName>Bob</displayName> 
    <address>[email protected]</address> 
</from> 
<to> 
    <address>[email protected]</address> 
</to> 
<bcc> 
    <displayName>Secret</displayName> 
    <address>[email protected]</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 
-------------------------------- -------------------------------------------------- 
[email protected]     to 
[email protected]     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 
-------------------------------- -------------------------------- 
[email protected]     Joe        to 
[email protected]     Bob        from 
[email protected]     NULL        to 
[email protected]     Secret       bcc 

有除标识的一切。

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

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

,也看到了这个帖子:

Finding node order in XML document in SQL server

+1

你有这个完全错误的全面... – muhmud 2013-04-10 15:07:24

+0

我更新了我的回应。 – granadaCoder 2013-04-10 15:19:52

+0

哦,你说得对。我后退了。哎呀! – granadaCoder 2013-04-10 17:01:46

相关问题