我需要解析下面的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>
答案 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;
此查询的棘手部分是将RowNumbers
与r
节点中Column
节点的位置相匹配。
CTE C
为每个RowNumber
返回Position
和RowNumber
的列表。该位置在xPath表达式r[sql:column("C.Position")]
中使用,以获取每个r
的{{1}}节点。
现在剩下的就是使用XML中的列定义动态构建和执行上述查询。
可以通过提取每个列定义并使用RowNumber
将它们连接在一起来完成。
for xml path('')
<子>
注意:使用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
子>