2016-11-16 76 views
0

我將通過應用於約60個表的觸發器創建的行存儲到單個審計表中。在SQL Server 2016中從xml列重新創建一行

我有一個xml列在行存儲英寸

如何重新創建隨機XML數據的行(在查詢我不知道,因爲所有的錶行存儲的XML結構的點(在這種情況下,節點)都與不同的列不同)

一個條目可以像這樣

<Log> 
    <id>2</id> 
    <text>232323</text> 
    <text1>2323</text1> 
    <text2>2323</text2> 
    <text3>2323</text3> 
    <text4>2323</text4> 
    <text5>2323</text5> 
</Log> 

和另一個條目可能看起來像這樣

<Log> 
    <id>3</id> 
    <tableName>ExcludeTables</tableName> 
</Log> 

現在,當我從logtable選擇其中id = 50我想看到的列和值在一個普通的SQL服務器數據行格式

感謝您的幫助

回答

1

SQL Server不動態支持創建列別名。實現這個與列名未知的唯一方法是動態創建的SQL

在這個例子中,我創建了一個模型表並插入兩行。

第一行將返回您的節點作爲鍵值對。

第二,動態地創建一個查詢,因爲你需要它返回的結果:

DECLARE @tbl TABLE(ID INT, SomeValue VARCHAR(100),AuditColumn XML) 
INSERT INTO @tbl VALUES 
(1,'Row 1' 
,N'<Log> 
    <id>2</id> 
    <text>232323</text> 
    <text1>2323</text1> 
    <text2>2323</text2> 
    <text3>2323</text3> 
    <text4>2323</text4> 
    <text5>2323</text5> 
</Log>') 
,(2,'Row 2' 
,N'<Log> 
    <id>3</id> 
    <tableName>ExcludeTables</tableName> 
</Log>'); 

- 這是您正在尋找

DECLARE @id INT=1; 

的ID --The結果是鍵值對

SELECT ID 
     ,SomeValue 
     ,nd.value('local-name(.)','nvarchar(max)') AS NodeName 
     ,nd.value('.','nvarchar(max)') AS NodeValue 
FROM @tbl AS t 
CROSS APPLY t.AuditColumn.nodes('/Log/*') A(nd) 
WHERE [email protected]; 

--The結果

名單10
+----+-----------+----------+-----------+ 
| ID | SomeValue | NodeName | NodeValue | 
+----+-----------+----------+-----------+ 
| 1 | Row 1  | id  | 2   | 
+----+-----------+----------+-----------+ 
| 1 | Row 1  | text  | 232323 | 
+----+-----------+----------+-----------+ 
| 1 | Row 1  | text1 | 2323  | 
+----+-----------+----------+-----------+ 
| 1 | Row 1  | text2 | 2323  | 
+----+-----------+----------+-----------+ 
| 1 | Row 1  | text3 | 2323  | 
+----+-----------+----------+-----------+ 
| 1 | Row 1  | text4 | 2323  | 
+----+-----------+----------+-----------+ 
| 1 | Row 1  | text5 | 2323  | 
+----+-----------+----------+-----------+ 

--dynamically創建SQL語句

DECLARE @cmd NVARCHAR(MAX)= 
(
    SELECT N'SELECT ' 
      + STUFF(
      (
       (
       SELECT ',''' + nd.value('.','nvarchar(max)') + ''' AS ' + QUOTENAME(nd.value('local-name(.)','nvarchar(max)')) 
       FROM @tbl AS t 
       CROSS APPLY t.AuditColumn.nodes('/Log/*') A(nd) 
       WHERE [email protected] 
       FOR XML PATH(''),TYPE).value('.','nvarchar(max)') 
       ),1,1,'' 
      ) 
); 

- 這是聲明

PRINT @cmd; 

SELECT '2' AS [id],'232323' AS [text],'2323' AS [text1],'2323' AS [text2],'2323' AS [text3],'2323' AS [text4],'2323' AS [text5] 

- 兼,這是它的執行

EXEC (@cmd); 

+----+--------+-------+-------+-------+-------+-------+ 
| id | text | text1 | text2 | text3 | text4 | text5 | 
+----+--------+-------+-------+-------+-------+-------+ 
| 2 | 232323 | 2323 | 2323 | 2323 | 2323 | 2323 | 
+----+--------+-------+-------+-------+-------+-------+ 
+0

太感謝你了,最好的回答:) –

+0

@AnatolyTrofimov請允許我一個提示:這是非常友好的s ay *謝謝 - 最佳答案*,但在答案的投票櫃檯下方勾選驗收檢查將更加友善。這將1)標記這個問題已解決2)使追隨者更容易找到最佳的解決方案3)支付點給回答者和4)支付點給你。一旦你自己超過了15分的邊界,你又被要求對貢獻進行投票。這是SO的方式來說聲謝謝。快樂編碼! – Shnugo

+0

沒問題,不知道那個抱歉 –