SQL Server 2005 Вставить родительские / дочерние данные XML - PullRequest
0 голосов
/ 16 апреля 2009

Учитывая 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

Я использую ADO.NET и .NET 3.5 с C #. У меня есть возможность отправки данных в виде типа параметра xml или типа текста. Я могу использовать новые вещи XQuery для SQL Server 2005 или стиль oldschool SQL 2000 OPENXML. Или, если на самом деле возможно выполнить эти вставки, используя SqlBulkInsert или что-то в этом роде, я не согласен с тем, что является самым быстрым (производительность важна в этой ситуации.) Спасибо за вашу помощь!


EDIT:

Похоже, вставка родительских / дочерних наборов действительно так сложна, как кажется. У меня не было возможности попробовать изучить LINQ to SQL и интегрировать эту инфраструктуру в мой продукт (мы сейчас находимся в цикле разработки!), И я не смог добиться особой тяги с помощью инструмента массовой вставки Xml, хотя он и кажется может быть использован для этой цели. В конце я реструктурировал таблицы для использования первичных ключей GUID в обеих таблицах и сгенерировал полные записи в API. Тогда я смог использовать ADO 2.0 SqlBulkInsert для отправки данных с высокой скоростью. Ответ получил Дэниел Миллер, потому что массовая загрузка SQL Server имела наилучшие шансы на успех без повторной архитектуры моего приложения.

Ответы [ 4 ]

5 голосов
/ 16 апреля 2009

Нечто подобное извлечет родителей, за которыми следуют дети с родительскими полями

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)
4 голосов
/ 23 мая 2013

С помощью слияния мы можем одновременно вставить родительские и дочерние данные

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
2 голосов
/ 16 апреля 2009

Звучит так, как вам нужно Массовая загрузка XML-кода SQL Server

0 голосов
/ 16 апреля 2009

Рассмотрим LINQ to SQL. Это действительно упростит вас в этом.

...