2012-12-18 36 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)