【问题标题】:shredding xml recursively into the database以递归方式将 xml 切碎到数据库中
【发布时间】:2014-07-19 14:28:55
【问题描述】:

我有以下 XML 数据和 Element 表。

DECLARE @input XML = '<root>
     <C1>
       <C2>
         <C3>           <C4>data1</C4>       </C3>         
       </C2>
       <C2>
         <C3>data2</C3>
       </C2>
     </C1>
     <D1>
        <D2>data3</D2>
        <D2>data4</D2>
     </D1>
    </root>'

元素表:(这只是一个示例,因此可以更改以匹配适当的解决方案。)

CREATE TABLE Element (  elementId INT IDENTITY PRIMARY KEY, 
elementName VARCHAR (200) NOT NULL, 
parentId INT,   
data VARCHAR(300) );

根据@input,根元素是C1和D1的父元素,那么C1是C2的父元素,...

SQL server 2012/2014 使用 CTE(或任何其他类型的 SQL 对象)编写存储过程以递归地将所有元素名称放入 Element 表的解决方案是什么?

在这种情况下,数据列填充数据,C4和第二个C3,D2元素有数据,其余元素为空。

我还看到了分层数据类型,我想知道这是否有助于解决这个问题?

【问题讨论】:

  • 您认为 HierarchyId 是否可以帮助您填充表格,或者您愿意更改表格结构以使用 HierarchyId?
  • 是的,我可以把表结构改成 HierarchyId 类型,目标是把 XML 切碎到数据库中,可以相应地制作所需的结构,当前的 Element 表是我能想到的第一个想法关于。
  • 您可能想看看使用OpenXml 语句创建边缘表。更多信息:msdn.microsoft.com/en-us/library/ms175160.aspx

标签: sql sql-server xml xquery xquery-sql


【解决方案1】:

使用OpenXML,您可以使用metaproperties 获得包含IDParentID 列的XML 表表示。

merge 中使用XML 查询将允许您在elementId 标识列和来自XML 的DOM 节点ID 之间的create a mapping 表。

最后一步是使用映射表更新parentId中的Element

SQL Fiddle

MS SQL Server 2008 架构设置

CREATE TABLE Element (  elementId INT IDENTITY PRIMARY KEY, 
elementName VARCHAR (200) NOT NULL, 
parentId INT,   
data VARCHAR(300) );

查询 1

declare @input xml = '
<root>
  <C1>
    <C2>
      <C3>
        <C4>data1</C4>
      </C3>
    </C2>
    <C2>
      <C3>data2</C3>
    </C2>
  </C1>
  <D1>
    <D2>data3</D2>
    <D2>data4</D2>
  </D1>
</root>';

-- OpenXML handle
declare @D int;

-- Table that capture output of merge with mapping between 
-- DOM node id and the identity column elementID in Element 
declare @T table
(
  ID int,
  ParentID int,
  ElementID int
);

-- Parse XML and get a handle
exec sp_xml_preparedocument @D output, @input;

-- Add rows to Element and fill the mapping table @T
merge into dbo.Element as E
using ( 
      select *
      from openxml(@D, '//*') with 
        (
          ID int '@mp:id',
          ParentID int '@mp:parentid',
          Data varchar(300) 'text()',
          ElementName varchar(200) '@mp:localname'
        )
      ) as S
on 0 = 1
when not matched by target then
  insert (elementName, data) values (S.ElementName, S.data)
output S.ID, S.ParentID, inserted.elementID into @T;

-- Update parentId in Elemet
update E
set parentId =  T2.ElementID
from dbo.Element as E
  inner join @T as T1
    on E.elementId = T1.ElementID
  inner join @T as T2
    on T1.ParentID = T2.ID


-- Relase the XML document
exec sp_xml_removedocument @D;

select *
from Element;

Results

| ELEMENTID | ELEMENTNAME | PARENTID |   DATA |
|-----------|-------------|----------|--------|
|         1 |        root |   (null) | (null) |
|         2 |          C1 |        1 | (null) |
|         3 |          C2 |        2 | (null) |
|         4 |          C3 |        3 | (null) |
|         5 |          C4 |        4 |  data1 |
|         6 |          C2 |        2 | (null) |
|         7 |          C3 |        6 |  data2 |
|         8 |          D1 |        1 | (null) |
|         9 |          D2 |        8 |  data3 |
|        10 |          D2 |        8 |  data4 |

【讨论】:

  • 谢谢你这很好用,我想知道 XQuery 是否可以做类似的事情,真正的 XML 文件比较粗,这样加载它们有意义吗?
  • @FredJand 我没有看到使用这种技术加载 XML 的任何问题。如果您担心目标表结构,我只能告诉您,这取决于您将如何查询数据以及您想用它做什么。 HierarchyID 可能是您的一个选项,或者您可以将整个 XML 转储到一个 XML 列中,每个 XML 文档有一行。如果您需要查询 XML,XML 索引和选择性 XML 索引 (SQL Server 2012 SP1) 可能会有所帮助。另一种选择是将 XML 结构模拟为带有连接的表。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-09
  • 2018-11-17
  • 2020-09-21
  • 2023-04-06
  • 1970-01-01
  • 2017-04-25
  • 1970-01-01
相关资源
最近更新 更多