简体   繁体   English

SQL Server 2005插入父/子xml数据

[英]SQL Server 2005 Insert parent/child xml data

Given an xml document that looks like this here: 给定一个如下所示的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>

What would be the fastest way in SQL Server 2005 to pass this document into a stored procedure which would insert the parent and child records into a set of tables, where the parent table has an identity column, and the child table refers to the parent by a foreign key? SQL Server 2005中将此文档传递到存储过程的最快方法是什么,该过程会将父记录和子记录插入一组表中,其中父表具有一个标识列,而子表通过以下方式引用父表外键?

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

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

I'm using ADO.NET and .NET 3.5 with C#. 我在C#中使用ADO.NET和.NET 3.5。 I have the option of sending the data as an xml parameter type or a text type. 我可以选择将数据作为xml参数类型或文本类型发送。 I can use the new-fangled sql 2005 XQuery stuff or the oldschool SQL 2000 OPENXML style. 我可以使用新式的sql 2005 XQuery东西或旧式的SQL 2000 OPENXML样式。 Or if it's actually possible to accomplish these inserts using SqlBulkInsert or something like that, I'm down with whatever is the fastest (performance is important in this situation.) Thanks for your help! 或者,如果实际上有可能使用SqlBulkInsert或类似的方法完成这些插入操作,那么我会选择最快的方法(在这种情况下,性能至关重要)。谢谢您的帮助!


EDIT: 编辑:

Looks like inserting parent/child sets is indeed as difficult as it seems. 看起来插入父/子集确实确实像看起来一样困难。 I was not in a position to try learning LINQ to SQL and integrating that framework into my product (we're in a dev cycle here!) and I wasn't able to get much traction with the Xml Bulk Insert tool although it appears it could be used for this purpose. 我无权尝试学习LINQ to SQL并将该框架集成到我的产品中(我们现在处于开发周期!),尽管看起来像Xml大容量插入工具,但我无法吸引很多人可用于此目的。 In the end I restructured the tables to use GUID primary keys on both tables, and generated the full records in the API. 最后,我重组了表以在两个表上使用GUID主键,并在API中生成了完整记录。 Then I was able to use ADO 2.0 SqlBulkInsert to send the data down at high speed. 然后,我能够使用ADO 2.0 SqlBulkInsert高速发送数据。 Answer awarded to Daniel Miller because SQL Server Bulk Load had the best chance of success without re-architecting my application altogether. 丹尼尔·米勒(Daniel Miller)回答了这一问题,因为SQL Server批量加载在没有完全重新架构我的应用程序的情况下具有最大的成功机会。

Something like this will extract parents followed by children with parent fields 这样的事情会吸引父母,然后是有父母领域的孩子

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)

By using merge we can insert parent and child data simultaneously 通过使用合并,我们可以同时插入父数据和子数据

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

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

Consider LINQ to SQL. 考虑使用LINQ to SQL。 It will actually simplify you on this one. 实际上,这将简化您的操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM