0

给定一个如下所示的 xml 文档:

  <parentRecords>
    <parentRecord field1="foo" field2="bar">
      <childRecord field1="test" field2="text" />
      <childRecord field1="test2" field2="text2" />
    </parentRecord>
    <parentRecord field1="foo2" field2="bar2">
      <childRecord field1="test3" field2="text3" />
      <childRecord field1="test4" field2="text4" />
    </parentRecord>
  </parentRecords>

在 SQL Server 2005 中,将此文档传递到存储过程中的最快方法是什么,该存储过程会将父记录和子记录插入一组表中,其中父表具有标识列,子表通过以下方式引用父表外键?

ParentTable
-----------
ParentID identity PK int
Field1 nvarchar
Field2 nvarchar

ChildTable
----------
ChildID identity PK int
ParentID FK int
Field1 nvarchar
Field2 nvarchar

我正在使用带有 C# 的 ADO.NET 和 .NET 3.5。我可以选择将数据作为 xml 参数类型或文本类型发送。我可以使用新奇的 sql 2005 XQuery 东西或老式的 SQL 2000 OPENXML 风格。或者,如果实际上可以使用 SqlBulkInsert 或类似的方法来完成这些插入,那么我对最快的方法感到失望(在这种情况下性能很重要。)感谢您的帮助!


编辑:

看起来插入父/子集确实像看起来一样困难。我无法尝试学习 LINQ to SQL 并将该框架集成到我的产品中(我们在这里处于开发周期!)并且我无法使用 Xml Bulk Insert 工具获得很大的吸引力,尽管它看起来可用于此目的。最后,我重组了表以在两个表上使用 GUID 主键,并在 API 中生成完整记录。然后我就可以使用 ADO 2.0 SqlBulkInsert 高速发送数据了。将答案授予 Daniel Miller,因为 SQL Server Bulk Load 在不完全重新构建我的应用程序的情况下获得了最大的成功机会。

4

4 回答 4

5

像这样的东西将提取父母,然后是具有父母字段的孩子

DECLARE @fooxml xml

SET @fooxml = N'<parentRecords>
    <parentRecord field1="foo" field2="bar">
      <childRecord field1="test" field2="text" />
      <childRecord field1="test2" field2="text2" />
    </parentRecord>
    <parentRecord field1="foo2" field2="bar2">
      <childRecord field1="test3" field2="text3" />
      <childRecord field1="test4" field2="text4" />
    </parentRecord>
  </parentRecords>'

SELECT
    x.item.value('@field1', 'varchar(100)') AS field1,
    x.item.value('@field2', 'varchar(100)') AS field2
FROM
    @fooxml.nodes('/parentRecords/parentRecord') x(item)

SELECT
    x.item.value('@field1', 'varchar(100)') AS field1,
    x.item.value('@field2', 'varchar(100)') AS field2,
    y.item.value('@field2', 'varchar(100)') AS childfield2,
    y.item.value('@field2', 'varchar(100)') AS childfield2
FROM
    @fooxml.nodes('/parentRecords/parentRecord') x(item)
    CROSS APPLY
    x.item.nodes('./childRecord') AS y(item)
于 2009-04-16T06:18:40.733 回答
4

通过使用合并,我们可以同时插入父数据和子数据

Create table #Master
(
 Id int Identity(1,1),
 MasterName Varchar(100)
)

Create Table #Intermediate
(MasterId int,
 ChildData XML)

 Create Table #Child
 (
 ChildId int identity(1,1),
 MasterId int,
 ChildName Varchar(100)
 )

Declare @XML XML='<Record>
                     <MasterRecord>
                        <Master>Master1</Master>
                        <ChildRecord>
                            <Child>Child11</Child>
                            <Child>Child12</Child>
                        </ChildRecord>
                     </MasterRecord>
                     <MasterRecord>
                        <Master>Master2</Master>
                        <ChildRecord>
                            <Child>Child21</Child>
                            <Child>Child22</Child>
                        </ChildRecord>
                     </MasterRecord>
                  </Record>'



MERGE #Master _MTR
USING (Select x.value('Master[1]','varchar(255)') AS masterName ,
              x.query('ChildRecord/Child') AS ChildData          
              From @XML.nodes('/Record/MasterRecord') e(x)) AS _XML
ON 1=0
WHEN NOT MATCHED THEN
INSERT (MasterName)
VALUES(_XML.MasterName)
OUTPUT INSERTED.Id, _XML.ChildData
INTO #Intermediate(MasterId,ChildData);


Insert Into #Child(MasterId,ChildName) 
Select  mas.Id, _data.value('(text())[1]', 'varchar(100)') as ChildName
from #Intermediate intr Inner Join #Master Mas
     On intr.MasterId=Mas.Id
CROSS APPLY ChildData.nodes('/Child') AS _chd(_data)

Select * from #Master
Select * from #Intermediate
select * from #Child
于 2013-05-23T18:01:51.110 回答
2

听起来您需要SQL Server XML 批量加载

于 2009-04-16T01:49:37.540 回答
-2

考虑 LINQ to SQL。它实际上会简化你。

于 2009-04-15T21:25:20.623 回答