Sql server 需要进行XML SQL优化
您好,我一直在尝试将SQL中XML的组和字段插入到两个表中。但解决方案要么不能解决我的问题,要么性能很慢,因为组和字段的数量可能会达到数十万 XML的一个示例:Sql server 需要进行XML SQL优化,sql-server,xml,tsql,optimization,xquery,Sql Server,Xml,Tsql,Optimization,Xquery,您好,我一直在尝试将SQL中XML的组和字段插入到两个表中。但解决方案要么不能解决我的问题,要么性能很慢,因为组和字段的数量可能会达到数十万 XML的一个示例: <?xml version="1.0" encoding="utf-16"?> <FB_Flow xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="htt
<?xml version="1.0" encoding="utf-16"?>
<FB_Flow
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" id="1">
<groups>
<FB_FlowGroup counter="1125" position="2" positionparent="0" id="0">
<fields>
<FB_FlowField>
<value>TEST1</value>
<counter>111</counter>
<lineposition>1</lineposition>
</FB_FlowField>
<FB_FlowField>
<value>TEST2</value>
<counter>222</counter>
<lineposition>2</lineposition>
<groupid>0</groupid>
</FB_FlowField>
<FB_FlowField>
<value>TEST3</value>
<counter>333</counter>
<lineposition>3</lineposition>
</FB_FlowField>
</fields>
</FB_FlowGroup>
<FB_FlowGroup counter="1126" position="3" positionparent="2" id="0">
<fields>
<FB_FlowField>
<value>TEST1</value>
<counter>18</counter>
<lineposition>1</lineposition>
</FB_FlowField>
</fields>
</FB_FlowGroup>
</groups>
</FB_Flow>
第二部分无法获取父组位置的所有字段:
insert into @Fields (intGroupPosition,vFieldValue,intFieldCounter,intFieldPosition)
SELECT
gposition = XTbl.Groups.value('@position', 'int'),
fValue = XTbl2.Fields.value('value[1]', 'varchar(max)'),
fcounter = XTbl2.Fields.value('counter[1]', 'int'),
fposition = XTbl2.Fields.value('lineposition[1]', 'int')
FROM
@FlowXML.nodes('/FB_Flow/groups/FB_FlowGroup') AS XTbl(Groups)
cross APPLY
Groups.nodes('fields/FB_FlowField') AS XTbl2(Fields)
我一直通过使用光标并通过position属性选择组来解决这个问题,但是性能非常差
DECLARE @GroupCounter int,
@GroupPosition int,
@GroupPositionParent int,
@GroupID int
DECLARE @Groups table
(
intGroupCounter int not null,
intGroupPosition int not null,
intGroupPositionParent int null default 0
)
insert into @Groups (intGroupCounter,intGroupPosition,intGroupPositionParent)
SELECT
gcounter = Groups.value('@counter[1]', 'int'),
gposition = Groups.value('@position[1]', 'int'),
gpositionparent = Groups.value('@positionparent[1]', 'int')
FROM
@FlowXML.nodes('/FB_Flow/groups/FB_FlowGroup') AS XTbl(Groups)
DECLARE cur cursor for
SELECT
intGroupCounter,
intGroupPosition,
intGroupPositionParent
FROM
@Groups
OPEN cur
FETCH NEXT FROM cur INTO @GroupCounter, @GroupPosition, @GroupPositionParent
WHILE @@FETCH_STATUS = 0
BEGIN
insert into FB_T_FlowGroups (FH_ID,DTC_GroupCounter,Position,PositionParent)
values (@FlowHeaderID,@GroupCounter,@GroupPosition,@GroupPositionParent)
select @GroupID = @@IDENTITY
--declare @Path varchar(max) = '/FB_Flow/groups/FB_FlowGroup[@position="sql:variable("@GroupPosition")"]/fields/FB_FlowField'
insert into FB_T_FlowGroupField (FlowGroupID,ItemValue,DTC_ItemCounter)
SELECT
@GroupID,
XTbl.Fields.value('value[1]', 'varchar(max)'),
XTbl.Fields.value('counter[1]', 'int')
FROM
@FlowXML.nodes('/FB_Flow/groups/FB_FlowGroup[@position=sql:variable("@GroupPosition")]/fields/FB_FlowField') AS XTbl(Fields)
FETCH NEXT FROM cur INTO @GroupCounter, @GroupPosition, @GroupPositionParent
END
CLOSE cur
DEALLOCATE cur
有什么想法吗?您的SQL Server版本是什么选择@@version 请在没有光标的情况下尝试以下方法。它将给您带来巨大的性能改进: XML属性不需要[1]位置。属性总是唯一的。 XML元素需要在XPath表达式文本中进行调整。 SQL
很好,解决了我的问题,谢谢,解释得很好。@JeffCorn,很高兴听到建议的解决方案对您有效。请别忘了把它标为答案。另外,请在这里投票:
DECLARE @GroupCounter int,
@GroupPosition int,
@GroupPositionParent int,
@GroupID int
DECLARE @Groups table
(
intGroupCounter int not null,
intGroupPosition int not null,
intGroupPositionParent int null default 0
)
insert into @Groups (intGroupCounter,intGroupPosition,intGroupPositionParent)
SELECT
gcounter = Groups.value('@counter[1]', 'int'),
gposition = Groups.value('@position[1]', 'int'),
gpositionparent = Groups.value('@positionparent[1]', 'int')
FROM
@FlowXML.nodes('/FB_Flow/groups/FB_FlowGroup') AS XTbl(Groups)
DECLARE cur cursor for
SELECT
intGroupCounter,
intGroupPosition,
intGroupPositionParent
FROM
@Groups
OPEN cur
FETCH NEXT FROM cur INTO @GroupCounter, @GroupPosition, @GroupPositionParent
WHILE @@FETCH_STATUS = 0
BEGIN
insert into FB_T_FlowGroups (FH_ID,DTC_GroupCounter,Position,PositionParent)
values (@FlowHeaderID,@GroupCounter,@GroupPosition,@GroupPositionParent)
select @GroupID = @@IDENTITY
--declare @Path varchar(max) = '/FB_Flow/groups/FB_FlowGroup[@position="sql:variable("@GroupPosition")"]/fields/FB_FlowField'
insert into FB_T_FlowGroupField (FlowGroupID,ItemValue,DTC_ItemCounter)
SELECT
@GroupID,
XTbl.Fields.value('value[1]', 'varchar(max)'),
XTbl.Fields.value('counter[1]', 'int')
FROM
@FlowXML.nodes('/FB_Flow/groups/FB_FlowGroup[@position=sql:variable("@GroupPosition")]/fields/FB_FlowField') AS XTbl(Fields)
FETCH NEXT FROM cur INTO @GroupCounter, @GroupPosition, @GroupPositionParent
END
CLOSE cur
DEALLOCATE cur
DECLARE @FlowXML XML =
N'<FB_Flow xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" id="1">
<groups>
<FB_FlowGroup counter="1125" position="2" positionparent="0" id="0">
<fields>
<FB_FlowField>
<value>TEST1</value>
<counter>111</counter>
<lineposition>1</lineposition>
</FB_FlowField>
<FB_FlowField>
<value>TEST2</value>
<counter>222</counter>
<lineposition>2</lineposition>
<groupid>0</groupid>
</FB_FlowField>
<FB_FlowField>
<value>TEST3</value>
<counter>333</counter>
<lineposition>3</lineposition>
</FB_FlowField>
</fields>
</FB_FlowGroup>
<FB_FlowGroup counter="1126" position="3" positionparent="2" id="0">
<fields>
<FB_FlowField>
<value>TEST1</value>
<counter>18</counter>
<lineposition>1</lineposition>
</FB_FlowField>
</fields>
</FB_FlowGroup>
</groups>
</FB_Flow>';
-- insert into @Groups (intGroupCounter,intGroupPosition,intGroupPositionParent)
SELECT gcounter = Groups.value('@counter', 'INT')
, gposition = Groups.value('@position', 'INT')
, gpositionparent = Groups.value('@positionparent', 'INT')
FROM @FlowXML.nodes('/FB_Flow/groups/FB_FlowGroup') AS XTbl(Groups);
--insert into @Fields (intGroupPosition,vFieldValue,intFieldCounter,intFieldPosition)
SELECT gposition = XTbl.Groups.value('@position', 'INT')
, fValue = XTbl2.Fields.value('(value/text())[1]', 'VARCHAR(MAX)')
, fcounter = XTbl2.Fields.value('(counter/text())[1]', 'INT')
, fposition = XTbl2.Fields.value('(lineposition/text())[1]', 'INT')
FROM @FlowXML.nodes('/FB_Flow/groups/FB_FlowGroup') AS XTbl(Groups)
CROSS APPLY Groups.nodes('fields/FB_FlowField') AS XTbl2(Fields);