2016-05-02 26 views
0

我有一個表保存xml數據。 xml如下Xml到tsql中的表

<responses> 
    <response> 
    <id>UniqueRowID</id> 
    <value>16</value> 
    </response> 
    <response> 
    <id>Language</id> 
    <value>en-GB</value> 
    </response> 
    <response> 
    <id>UserId</id> 
    <value>21</value> 
    </response> 
</responses> 

在下一列中可以有其他一些數據。價值是所有人共同的價值。但其中一些ID可能不在另一行。

現在我需要一個表格,格式如下。我知道所有列應該顯示。如果某個列不在xml中,它可以是空白的。我怎樣才能做到這一點?

UniqueRowID語言用戶ID

--- ------- ------

16 EN-GB 21

我看到了一些相似,但沒有對我的作品,因爲xml在這些示例中有不同的表示方式

+0

可以使用SSIS?這是一次性進口嗎? – TheNorthWes

+0

我打算通過數據創建一個ssrs報告 –

+0

這不能回答我的問題,但我認爲如果這是一個報告,那麼您需要重複加載數據。 SSIS是一個選項嗎? – TheNorthWes

回答

1

我把這個作爲第二個答案,因爲它是一個完全不同的方法。有了這個代碼,你可以閱讀這個結構的任何XML。使用動態SQL能夠創建動態的列名:

CREATE TABLE #tmpTbl (YourXml XML); 
INSERT INTO #tmpTbl VALUES 
('<responses> 
    <response> 
    <id>UniqueRowID</id> 
    <value>16</value> 
    </response> 
    <response> 
    <id>Language</id> 
    <value>en-GB</value> 
    </response> 
    <response> 
    <id>UserId</id> 
    <value>21</value> 
    </response> 
    <response> 
    <id>SomeOther1</id> 
    <value>SO1</value> 
    </response> 
    <response> 
    <id>SomeOther2</id> 
    <value>SO2</value> 
    </response> 
</responses>'); 

DECLARE @columnNames VARCHAR(MAX)= 
(
    STUFF(
    (
     SELECT ',[' + B.value('id[1]','varchar(max)')+ ']' 
     FROM #tmpTbl 
     CROSS APPLY YourXml.nodes('/responses/response') AS A(B) 
     FOR XML PATH('') 
    ),1,1,''  
    ) 
); 

DECLARE @cmd VARCHAR(MAX)= 
'SELECT p.* 
FROM 
(
    SELECT B.value(''id[1]'',''varchar(max)'') AS ColumnName 
      ,B.value(''value[1]'',''varchar(max)'') AS ColumnValue 
    FROM #tmpTbl 
     CROSS APPLY YourXml.nodes(''/responses/response'') AS A(B) 
) AS tbl 
PIVOT 
(
    MIN(ColumnValue) FOR ColumnName IN(' + @columnNames + ') 
) As p'; 

EXEC(@cmd); 
GO 

DROP TABLE #tmpTbl; 

結果:

UniqueRowID Language UserId SomeOther1 SomeOther2 
16   en-GB  21  SO1   SO2 
+0

昨天我採用了同樣的方式。感謝您的更新。我從第一個答案中獲得了數據。我給了樞軸 –

2

這是一個簡單的XML結構。如果您需要將它「拼合」到SQL表中,可以使用XPATH語法來完成,如下所示。

declare @xml xml = ' 
<responses> 
    <response> 
    <id>UniqueRowID</id> 
    <value>16</value> 
    </response> 
    <response> 
    <id>Language</id> 
    <value>en-GB</value> 
    </response> 
    <response> 
    <id>UserId</id> 
    <value>21</value> 
    </response> 
</responses> 
'; 
select 
    T.c.value('(id)[1]','nvarchar(100)') as UniqueRowID 
,T.c.value('(value)[1]','nvarchar(100)') as Language 
from 
    @xml.nodes('/responses/response') T(c) 

,這將給你這樣的數據:

UniqueRowID | Language 
====================== 
UniqueRowID | 16 
Language | en-GB 
UserId  | 21 

我有點困惑你的意思是,當你寫:

在下一欄也可以有一些其他數據。價值是所有人共同的價值。但其中一些ID可能不在另一行。

它似乎也是以一種不太適合XML的方式構造這些數據。理想情況下,每個響應元素都應具有相同的組件。

你可能會考慮更多的東西像這樣(只深思):

<responses> 
    <response> 
    <UniqueRowID>100</UniqueRowID> 
    <UserId>16</id> 
    <Language>EN-GB</value> 
    </response> 
    <response> 
    <UniqueRowID>200</UniqueRowID> 
    <UserId>17</id> 
    <Language>ES</value> 
    </response> 
    <response> 
    <UniqueRowID>300</UniqueRowID> 
    <UserId>18</id> 
    <Language>DE</value> 
    </response> 
</responses> 
+0

欣賞努力。但查詢將導致2列。我需要3列結果(如果用戶選擇3列)。在下一列中可以有其他一些數據意味着下一行可能沒有userid。相反,它可能有發起者。如果用戶選擇他對發起人感興趣,只有lanuguage纔會顯示這兩列僅作爲結果 –

+0

xml格式的數據也只在我的情況下才是好的。它實際上以id&value的形式保存了一個關鍵值對的列表 –

+1

@BineshNambiarC我是否理解正確?你希望所有'response'節點都被視爲鍵/值對,其值爲數據,id作爲列名在單行中?請檢查我的答案...您可以根據需要添加任意數量的列。缺少的將保持空白... – Shnugo

1

試試這樣說:

DECLARE @xml XML= 
'<responses> 
    <response> 
    <id>UniqueRowID</id> 
    <value>16</value> 
    </response> 
    <response> 
    <id>Language</id> 
    <value>en-GB</value> 
    </response> 
    <response> 
    <id>UserId</id> 
    <value>21</value> 
    </response> 
</responses>' 

SELECT @xml.value('(/responses/response[id="UniqueRowID"]/value)[1]','int') AS UniqueRowID 
     , @xml.value('(/responses/response[id="Language"]/value)[1]','varchar(max)') AS Language 
     , @xml.value('(/responses/response[id="UserId"]/value)[1]','int') AS UserId 

結果

UniqueRowID Language UserId 
16   en-GB  21