2009-04-15 8 views
0

Étant donné un document XML qui ressemble à ceci ici:SQL Server 2005 Insérez les données xml parent/enfant

<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> 

Quelle serait la plus rapide dans SQL Server 2005 pour passer ce document dans une procédure stockée qui insérerait les enregistrements parent et enfant dans un ensemble de tables, où la table parent a une colonne d'identité et la table enfant fait référence au parent par une clé étrangère? J'utilise ADO.NET et .NET 3.5 avec C#. J'ai la possibilité d'envoyer les données en tant que type de paramètre xml ou type de texte. Je peux utiliser le truc new-fangled sql 2005 XQuery ou le style oldschool SQL 2000 OPENXML. Ou s'il est réellement possible d'accomplir ces insertions en utilisant SqlBulkInsert ou quelque chose comme ça, je suis en panne avec ce qui est le plus rapide (la performance est importante dans cette situation.) Merci pour votre aide!


EDIT:

On dirait que l'insertion fixe parent/enfant est en effet aussi difficile que cela puisse paraître. Je n'étais pas en mesure d'essayer l'apprentissage de LINQ to SQL et d'intégrer ce framework dans mon produit (nous sommes dans un cycle de développement ici!) Et je n'ai pas pu obtenir beaucoup de traction avec l'outil Xml Bulk Insert pourrait être utilisé à cette fin. À la fin, j'ai restructuré les tables pour utiliser les clés primaires GUID sur les deux tables, et j'ai généré les enregistrements complets dans l'API. Ensuite, j'ai été en mesure d'utiliser ADO 2.0 SqlBulkInsert pour envoyer les données à haute vitesse. Réponse donnée à Daniel Miller parce que SQL Server Bulk Load a eu les meilleures chances de succès sans ré-architecturer complètement mon application.

Répondre

2

On dirait que vous avez besoin SQL Server XML Bulk Load

+0

Cela ressemble vraiment à ce que je cherche! Existe-t-il un moyen de configurer le fichier de schéma pour la relation parent/enfant, de sorte que les lignes enfant obtiennent la clé étrangère de leur parent? –

+0

Désolé, je l'ai seulement trouvé, je ne l'ai jamais vraiment utilisé! –

-2

Envisagez LINQ to SQL. Cela vous simplifiera réellement sur celui-ci.

+0

faire vous pensez que cela offrirait un avantage de performance à 100k + records? –

+0

Vous ne devriez pas voir beaucoup de différence. Essayez de charger des données factices 100K et testez-le vous-même. –

5

Quelque chose comme cela extraira les parents suivis par les enfants avec des champs parents

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

En utilisant fusionnons nous pouvons insérer des données parent et enfant simultanément

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 
+1

Belle réponse +1. –

+1

Ouais, ressemble beaucoup à [celui-ci] (http://stackoverflow.com/questions/16715392/bulk-insert-in-parent-and-child-table-using-sp-xml-preparedocument/16720415#16720415) . :-) –

+0

même si vous avez copié la réponse, c'est quand même un très bon. – MalachiteBR