我有一个存储过程,它将XML文档作为一个类似于以下结构的参数:
<grandparent name="grandpa bob">
<parent name="papa john">
<children>
<child name="mark" />
<child name="cindy" />
</children>
</parent>
<parent name="papa henry">
<children>
<child name="mary" />
</children>
</parent>
</grandparent>
我的要求是“扁平化”这些数据,以便可以将其插入临时表并在程序中进一步操作,因此上面的XML变为:
Grandparent Name Parent Name Child Name
---------------- --------------- ---------------
grandpa bob papa john mark
grandpa bob papa john cindy
grandpa bob papa henry mary
目前正在使用SQL Server XML节点完成:
SELECT
VIRT.node.value('../../../@name','varchar(15)') 'Grandparent Name',
VIRT.node.value('../../@name','varchar(15)') 'Parent Name',
VIRT.node.value('@name','varchar(15)') 'Child Name'
FROM
@xmlFamilyTree.nodes('/grandparent/parent/children/child') AS VIRT(node)
这很有效,直到我开始在程序中抛出大量数据(即1000 + child
个节点),此时这会停止并需要1到2分钟才能执行。我想这可能是因为我从最低级别(<child
)开始,然后为每次出现遍历XML文档。将这个单个查询拆分为3个块(每个节点需要一个数据)可以提高性能吗?鉴于这些节点中没有一个节点上有“键”,我可以用它来加入备份,有人可以提供任何指示我可以这样做吗?
答案 0 :(得分:7)
我在网上看了一遍之后似乎回答了我自己的问题:
SELECT
grandparent.gname.value('@name', 'VARCHAR(15)'),
parent.pname.value('@name', 'VARCHAR(15)'),
child.cname.value('@name', 'VARCHAR(15)')
FROM
@xmlFamilyTree.nodes('/grandparent') AS grandparent(gname)
CROSS APPLY
grandparent.gname.nodes('*') AS parent(pname)
CROSS APPLY
parent.pname.nodes('children/*') AS child(cname)
使用CROSS APPLY
我可以选择顶级grandparent
节点,并使用它来选择子节点parent
,依此类推。使用这种方法,我将查询从 1分30秒下执行到 6秒。
有趣的是,如果我使用“旧”OPEN XML
方法检索相同数据,则查询将在 1秒中执行!
根据传入文档的预期大小/复杂程度,您可能需要根据具体情况逐步使用这两种技术。