XML到SQL结果集。多嵌套级别
本质上,我正在尝试使用SQL将XML转换为平面数据结构 我的XML采用以下格式我已将XML更改为一个子集,以使我的示例更简单:XML到SQL结果集。多嵌套级别,sql,xml,tsql,Sql,Xml,Tsql,本质上,我正在尝试使用SQL将XML转换为平面数据结构 我的XML采用以下格式我已将XML更改为一个子集,以使我的示例更简单: <Actions> <AddComponent> <Action> <DataItem> <GroupId>1</GroupId> <Data>
<Actions>
<AddComponent>
<Action>
<DataItem>
<GroupId>1</GroupId>
<Data>
<Id>100</Id>
<Value>Value A</Value>
<Children>
<Data>
<Id>200</Id>
<Value>Value B</Value>
<Children>
<Data>
<Id>300</Id>
<Value>Value C1</Value>
</Data>
<Data>
<Id>301</Id>
<Value>Value C2</Value>
<Children />
</Data>
</Children>
</Data>
</Children>
</Data>
</DataItem>
<DataItem>
<GroupId>2</GroupId>
<Data>
<Id>101</Id>
<Value>Value A</Value>
<Children>
<Data>
<Id>200</Id>
<Value>Value B</Value>
<Children>
<Data>
<Id>302</Id>
<Value>Value C3</Value>
</Data>
</Children>
</Data>
</Children>
</Data>
</DataItem>
</Action>
</AddComponent>
</Actions>
我不确定递归遍历“Children”元素的最佳方法。因为子项的数量可能是无限的。检查此查询是否有帮助:
DECLARE @XML XML = '<Actions><AddComponent><Action><DataItem><GroupId>1</GroupId><Data><Id>100</Id><Value>Value A</Value><Children><Data><Id>200</Id><Value>Value B</Value><Children><Data><Id>300</Id><Value>Value C1</Value></Data><Data><Id>301</Id><Value>Value C2</Value><Children /></Data></Children></Data></Children></Data></DataItem><DataItem><GroupId>2</GroupId><Data><Id>101</Id><Value>Value A</Value><Children><Data><Id>200</Id><Value>Value B</Value><Children><Data><Id>302</Id><Value>Value C3</Value></Data></Children></Data></Children></Data></DataItem></Action></AddComponent></Actions>';
;WITH cte
AS (SELECT c.value('(GroupId)[1]', 'varchar(30)') groupid,
c.value('(Data/Id)[1]', 'varchar(30)') id,
c.value('(Data/Value)[1]', 'varchar(30)') value,
c.query('Data/Children') AS childdata,
Cast(NULL AS VARCHAR(30)) AS parentId
FROM (SELECT @xml) temp(x)
CROSS apply x.nodes('//Actions/AddComponent/Action/DataItem') tabl(c)
UNION ALL
SELECT groupid,
c.value('(Id)[1]', 'varchar(30)') id,
c.value('(Value)[1]', 'varchar(30)') value,
c.query('Children') AS childdata,
Cast(cte.id AS VARCHAR(30)) AS parentId
FROM cte
CROSS apply childdata.nodes('/Children/Data') tabl(c))
SELECT groupid,
id,
value,
parentId
FROM cte
ORDER BY groupid,id
正如您在我的CTE中所看到的,我首先提取了所有父节点数据及其子XML,然后递归地从子XML获取所有子数据。选择DI.X.value'GroupId/text[1],'int'作为GroupId,
D.X.value'Id/text[1],'int'作为Id,
D.X.value'value/text[1],'nvarchar50'作为值,
D.X.value“../../Id/text[1]”,ParentID为“int”
从@XML.nodes'/Actions/AddComponent/Action/DataItem'作为DIX
交叉应用DI.X.nodes.//Data作为DX
.//数据将递归地为您提供所有数据节点
注意:使用父轴.././Id/text[1]获取ParentID可能会导致性能下降。用您的数据尝试一下,看看它的性能是否可以接受
更新:
在节点调用中执行父轴看起来会为您提供更好的查询计划
选择DI.X.value'GroupId/text[1],'int'作为GroupId,
D.X.value'Id/text[1],'int'作为Id,
D.X.value'value/text[1],'nvarchar50'作为值,
P.X.value'text[1],'int'作为ParentID
从@XML.nodes'/Actions/AddComponent/Action/DataItem'作为DIX
交叉应用DI.X.nodes.//Data作为DX
外部应用D.X.nodes'../../Id'作为PX
选中此项:
DECLARE @XML XML = '<Actions><AddComponent><Action><DataItem><GroupId>1</GroupId><Data><Id>100</Id><Value>Value A</Value><Children><Data><Id>200</Id><Value>Value B</Value><Children><Data><Id>300</Id><Value>Value C1</Value></Data><Data><Id>301</Id><Value>Value C2</Value><Children /></Data></Children></Data></Children></Data></DataItem><DataItem><GroupId>2</GroupId><Data><Id>101</Id><Value>Value A</Value><Children><Data><Id>200</Id><Value>Value B</Value><Children><Data><Id>302</Id><Value>Value C3</Value></Data></Children></Data></Children></Data></DataItem></Action></AddComponent></Actions>';
;WITH cte
AS (SELECT c.value('(GroupId)[1]', 'varchar(30)') groupid,
c.value('(Data/Id)[1]', 'varchar(30)') id,
c.value('(Data/Value)[1]', 'varchar(30)') value,
c.query('Data/Children') AS childdata,
Cast(NULL AS VARCHAR(30)) AS parentId
FROM (SELECT @xml) temp(x)
CROSS apply x.nodes('//Actions/AddComponent/Action/DataItem') tabl(c)
UNION ALL
SELECT groupid,
c.value('(Id)[1]', 'varchar(30)') id,
c.value('(Value)[1]', 'varchar(30)') value,
c.query('Children') AS childdata,
Cast(cte.id AS VARCHAR(30)) AS parentId
FROM cte
CROSS apply childdata.nodes('/Children/Data') tabl(c))
SELECT groupid,
id,
value,
parentId
FROM cte
ORDER BY groupid,id