从重复元素及其子元素\属性中获取一张表中的多条XML记录
Posted
技术标签:
【中文标题】从重复元素及其子元素\\属性中获取一张表中的多条XML记录【英文标题】:Get multiple XML records in one table from a repeated element and its subelements \ attributes从重复元素及其子元素\属性中获取一张表中的多条XML记录 【发布时间】:2020-07-06 09:16:35 【问题描述】:目前的算法使用 ... ,x.n.value ... [1] 方法,它只检索第一条记录。用什么更好地检索所有现有元素的值(以及层次结构中的其他记录)?
主要的 XML 提取基于类似的模型
SELECT..
CAST(decompress([Data]) AS NVARCHAR(MAX)
FROM..
然后去:
;WITH XMLNAMESPACES (DEFAULT 'urn://somenamespacename')
INSERT INTO [DB].[dbo].[table] (
ID
,Att1
,Att2
,SubAtt1
,SubAtt2
,Lenght
,Neighbour
)
SELECT
@ID
,x.n.value('(@Att1)[1]', 'VARCHAR(100)')
,x.n.value('(@Att2)[1]', 'VARCHAR(100)')
,x.n.value('(*:Neighbours/*:SubBorder/@SubAtt1)[1]', 'VARCHAR(100)')
,x.n.value('(*:Neighbours/*:SubBorder/@SubAtt2)[1]', 'VARCHAR(100)')
,x.n.value('(*:Edge/*:Lenght)[1]', 'int')
,x.n.value('(*:Edge/*:Neighbour)[1]', 'VARCHAR(100)')
FROM @xml.nodes('/root/*:TOP/*:Border') as x(n)
XML 示例
<root>
<TOP ID="1">
<Border Att1="BorderValue1" Att2="BorderValue2">
<Edge>
<Length>100</Length>
<Neighbours>
<Neighbour>alpha</Neighbour>
<SubBorder SubAtt1="SubValue1" SubAtt2="SubValue2" />
</Neighbours>
</Edge>
</Border>
<Border Att1="BorderValue3" Att1="BorderValue4">
<Edge>
<Length>300</Length>
<Neighbours>
<Neighbour>bravo</Neighbour>
<SubBorder SubAtt1="SubValue3" SubAtt2="SubValue4" />
</Neighbours>
</Edge>
</Border>
</TOP>
</root>
期望的输出
ID Att1 Att2 SubAtt1 SubAtt2 Lenght Neighbour
1 BorderValue1 BorderValue2 SubValue1 SubValue2 100 alpha
1 BorderValue3 BorderValue4 SubValue3 SubValue4 300 bravo
【问题讨论】:
【参考方案1】:您正在声明一个命名空间,但 XML 中没有命名空间部分... 此外,还有一个双重属性“Att1”,估计是错字
但是,您似乎正在寻找.nodes()
。此函数检索派生表中的重复元素:
您的 XML(没有命名空间):
DECLARE @xml XML=
N'<root>
<TOP ID="1">
<Border Att1="BorderValue1" Att2="BorderValue2">
<Edge>
<Length>100</Length>
<Neighbours>
<Neighbour>alpha</Neighbour>
<SubBorder SubAtt1="SubValue1" SubAtt2="SubValue2" />
</Neighbours>
</Edge>
</Border>
<Border Att1="BorderValue3" Att2="BorderValue4">
<Edge>
<Length>300</Length>
<Neighbours>
<Neighbour>bravo</Neighbour>
<SubBorder SubAtt1="SubValue3" SubAtt2="SubValue4" />
</Neighbours>
</Edge>
</Border>
</TOP>
</root>';
--查询
SELECT @xml.value('(/root/TOP/@ID)[1]','int') AS ID
,brd.value('@Att1','nvarchar(max)') AS Att1
,brd.value('@Att2','nvarchar(max)') AS Att2
,brd.value('(Edge/Length/text())[1]','decimal(10,4)') AS [Length]
,nghbs.value('(Neighbour/text())[1]','nvarchar(max)') AS Border_Neighbour
,nghbs.value('(SubBorder/@SubAtt1)[1]','nvarchar(max)') AS Border_SubAtt1
,nghbs.value('(SubBorder/@SubAtt2)[1]','nvarchar(max)') AS Border_SubAtt2
FROM @xml.nodes('root/TOP/Border') ATU_2x_check(brd)
OUTER APPLY brd.nodes('Edge/Neighbours') B(nghbs);
简而言之:
我们可以直接挑ID(不重复) 我们使用.nodes()
来获得重复的<Border>
元素
我们可以更深入地研究使用带有相对 XPath 的 .nodes()
重复 <Neighbours>
我们可以使用.value()
来读取给定片段的值。
【讨论】:
@Shnugo谢谢!我是否正确理解,对于所有元素的正确解析,使用层次结构中的最低元素进行外部应用就足够了?在这种情况下,您不需要额外的外部应用(例如,使用Length
元素)
普通构造'.value...nvarchar(max)')
和构造(/text())[1]','nvarchar(max)
之间有显着区别吗?两种方法我都试过了,结果是一样的。
@XSLT-explorer,您需要 nodes() 来检索作为派生集的重复节点,并且对于单个值(相对于当前节点的任何单例 xpath)不需要它。 /text() 将加快查询速度,在这种情况下您需要它:<a>a1<b>inner</b>a2</a>
。 a1
和a2
是<a>
下方的不同文本节点以上是关于从重复元素及其子元素\属性中获取一张表中的多条XML记录的主要内容,如果未能解决你的问题,请参考以下文章