解析XML数据并将其保存到SQL Server中的临时表中

时间:2014-05-08 05:25:14

标签: sql sql-server

我需要解析下面的XML并返回结果。 Column元素将以不同的DestinationColumnCode属性增长。所以我需要让脚本动态化。

结果:

RowNumbers      Code                      Pay1_515
73123            5570, Industry1, 1       10
73124            5570, Industry2, 2       10

示例XML:

 <?xml version="1.0" encoding="utf-8"?>
    <CookedData>
     <RowNumbers>
        <rn v="73123" />
        <rn v="73124" />
    </RowNumbers>
     <Column DestinationColumnCode="Code">
        <r v="5570, Industry1, 1" />
        <r v="5570, Industry2, 2" />
    </Column>
    <Column DestinationColumnCode="Pay1_515">
       <r v="10" />
        <r v="10" />
    </Column>
    </CookedData>

1 个答案:

答案 0 :(得分:6)

使用输出中的动态列数,您需要动态构建查询。

但首先我们需要弄清楚该查询会是什么样子,因为一旦我们对此进行动态处理,它看起来会有点复杂。

使用此XML变量声明:

declare @XML xml = '<?xml version="1.0" encoding="utf-8"?>
<CookedData>
  <RowNumbers>
    <rn v="73123" />
    <rn v="73124" />
  </RowNumbers>
  <Column DestinationColumnCode="Code">
    <r v="5570, Industry1, 1" />
    <r v="5570, Industry2, 2" />
  </Column>
  <Column DestinationColumnCode="Pay1_515">
    <r v="10" />
    <r v="10" />
  </Column>
</CookedData>';

查询可能如下所示:

with C as
(
  select T.X.value('@v', 'int') as RowNumber,
         row_number() over(order by T.X) as Position
  from @XML.nodes('/CookedData/RowNumbers/rn') as T(X)
)
select C.RowNumber,
       @XML.value('(/CookedData/Column[@DestinationColumnCode = "Code"]/r[sql:column("C.Position")]/@v)[1]', 'nvarchar(max)') as Code,
       @XML.value('(/CookedData/Column[@DestinationColumnCode = "Pay1_515"]/r[sql:column("C.Position")]/@v)[1]', 'nvarchar(max)') as Pay1_515
from C;

此查询的棘手部分是将RowNumbersr节点中Column节点的位置相匹配。

CTE C为每个RowNumber返回PositionRowNumber的列表。该位置在xPath表达式r[sql:column("C.Position")]中使用,以获取每个r的{​​{1}}节点。

现在剩下的就是使用XML中的列定义动态构建和执行上述查询。

可以通过提取每个列定义并使用RowNumber将它们连接在一起来完成。

for xml path('')

SQL Fiddle

<子> 注意:使用declare @SQL nvarchar(max) set @SQL = ' with C as ( select T.X.value(''@v'', ''int'') as RowNumber, row_number() over(order by T.X) as Position from @XML.nodes(''/CookedData/RowNumbers/rn'') as T(X) ) select C.RowNumber' + ( select ', @XML.value(''(/CookedData/Column[@DestinationColumnCode = "'+T.Name+'"]/r[sql:column("C.Position")]/@v)[1]'', ''nvarchar(max)'') as '+quotename(T.Name) from ( select T.X.value('@DestinationColumnCode', 'nvarchar(max)') from @XML.nodes('/CookedData/Column') as T(X) ) as T(Name) for xml path(''), type).value('text()[1]', 'nvarchar(max)')+' from C;'; --print @SQL exec sp_executesql @SQL, N'@XML xml', @XML; 获取XML文档中节点位置的技术依赖于SQL Server解析XML的内部实现的知识。 Microsoft未记录该行为。 Adam Machanic在此发表了博文:Uniquely Identifying XML Nodes with DENSE_RANK