【问题标题】:Flattening hierarchical XML in SQL using the nodes() method使用 nodes() 方法在 SQL 中展平分层 XML
【发布时间】:2011-04-27 07:03:19
【问题描述】:

我有一个将 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 分钟才能执行。我认为这可能是因为我从最低级别 (&lt;child) 开始,然后每次出现都遍历 XML 文档。将这个单个查询分成 3 个块(每个节点一个我需要数据的块)会提高性能吗?鉴于这些节点上都没有我可以用来加入备份的“密钥”,任何人都可以提供任何指示我可以如何去做吗?

【问题讨论】:

  • 从 xml 创建基于行的数据的过程通常称为“粉碎”,顺便说一句。

标签: sql xml sql-server-2005 tsql sql-server-2008


【解决方案1】:

在网上多看了一下之后,我似乎已经回答了我自己的问题:

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 秒内执行!

您似乎必须根据传入文档的预期大小/复杂性逐个处理这两种技术的使用。

【讨论】:

  • 这在 SQLServer2005 中有效吗?我在第一个 CROSS APPLY 上得到一个错误(带有非常相似的查询) - 即你说grandparent.gname.nodes 我得到Invalid object name datatask.dt.nodes (这是我的等价物)。这实际上是我所期望的,因为标准查询不会让您在同一 FROM 语句中使用别名...
  • 在 sql server 2012 中效果很好,非常感谢这个答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-25
  • 1970-01-01
  • 2020-11-21
  • 1970-01-01
  • 1970-01-01
  • 2015-12-05
  • 1970-01-01
相关资源
最近更新 更多