2012-12-18 35 views
4

我想將XML字段拆分爲多列數據集。 XML看起來像:T-SQL將XML字段轉換爲多列數據集

<simple> 
    <propertyid> 
     <value>p1</value> 
     <value>p2</value> 
     <value>p3</value> 
     <value>p4</value> 
    </propertyid> 
    <complexid> 
     <value>c1</value> 
     <value>c2</value> 
     <value>c3</value> 
    </complexid> 
</simple> 

我試圖做這樣的事情(每次我使用XML在TSQL我覺得butthurt時間,所以我的代碼是錯誤的):

;WITH source AS (
    SELECT CAST(@xmlstring AS XML) AS x 
) 
SELECT 
    items.item.query('.') 
FROM source 
CROSS APPLY x.nodes('/simple/*/value') AS items(item) 

預期的數據集:

ColumnName  Value 
------------------------ 
propertyid  p1 
propertyid  p2 
propertyid  p3 
propertyid  p4 
complexid  c1 
complexid  c2 
complexid  c3 

我如何獲得所需的結果? 也許你可以推薦使用T-SQL + XML + XQuery解釋和示例的好資源?

回答

3

這裏是我自己用1個CROSS解決方案適用於:

;WITH source AS (
    SELECT CAST(@xmlstring AS XML) AS x 
) 
SELECT 
    items.item.value('local-name(..)', 'varchar(300)') AS ColumnName, 
    items.item.value('text()[1]', 'varchar') AS Value 
FROM source 
CROSS APPLY x.nodes('/simple/*/value') AS items(item) 

主要是我沒能訪問父節點,我想用戶 '../本地名稱()',但local-name()需要XPath來顯示diplay名稱。之後,顯示家長節點名稱變得容易。

5

嘗試這樣:

;WITH source AS (
    SELECT CAST(@xmlstring AS XML) AS x 
) 
SELECT 
    ColumnName = XTbl.Parent.value('local-name(.)', 'varchar(50)'), 
    [Value] = XTbl2.ChildValues.value('(.)[1]', 'varchar(20)') 
FROM source 
CROSS APPLY 
    x.nodes('/simple/*') AS XTbl(Parent) 
CROSS APPLY 
    XTbl.Parent.nodes('value') AS XTbl2(ChildValues) 

這是否對你的工作?我在我的情況下得到所需的輸出(使用助手錶)。

See this SQL Fiddle as a demo

+0

不錯,謝謝! –

1

根據你的要求建議的和XQuery的解決方案,那就是:

declare function local:createTestDoc() as node()* { 
    <simple> 
     <propertyid> 
      <value>p1</value> 
      <value>p2</value> 
      <value>p3</value> 
      <value>p4</value> 
     </propertyid> 
     <complexid> 
      <value>c1</value> 
      <value>c2</value> 
      <value>c3</value> 
     </complexid> 
    </simple> 
}; 

declare function local:doProcessing($arg as node()*) as xs:string* { 
    let $simpleElement := $arg 

    return (
     concat("ColumnName", " ", "Value") 
     , 
     for $propertyId in $simpleElement/propertyid/* 
     return (
      concat("propertyid", " ", data($propertyId)) 
     ) 
     , 
     for $complexId in $simpleElement/complexid/* 
     return (
      concat("complexid", " ", data($complexId)) 
     ) 
    ) 
}; 

local:doProcessing(local:createTestDoc()) 

而不是使用本地的:createTestDoc(),你將不得不包括使用類似文檔:

declare variable $myDoc := doc("urlToDoc"); 

並將其傳遞給本地:doProcessing()fn。

local:doProcessing($myDoc)