2013-04-10 71 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

相關問題