Insertion en bloc dans la table parent et enfant à l'aide de sp_xml_preparedocument

J'utilise sp_xml_preparedocument pour l'insertion en bloc. Mais je veux faire l'insertion en vrac dans la table parente, get scope_identity pour chaque nouvelle ligne insérée, puis insert en bloc dans la table enfant.

Je peux faire ceci en prenant la variable de table pour la table parent dans la procédure et insert datatables dans cette table que je supposé insert dans la table parente. Passez maintenant en boucle dans chaque ligne du slider, insérez-la dans la table actuelle puis dans la table enfant.

Mais y a-t-il une façon de battre sans slider? Je veux une solution optimale

Si vous utilisez SQL Server 2008 ou une version ultérieure, vous pouvez utiliser la fusion comme décrit dans cette question .

Créez une variable de table qui va capturer l'ID généré à partir de la table parent avec le XML enfant lors d'une fusion avec Parent . Puis insérez dans Child partir de la variable de table.

Remarque: j'utilise le type de données XML au lieu de openxml.

Les tables:

 create table Parent ( ParentID int identity primary key, Name varchar(10) not null ); create table Child ( ChildID int identity primary key, Name varchar(10) not null, ParentID int not null references Parent(ParentID) ); 

XML:

 <root> <parent> <name>parent 1</name> <child> <name>child 1</name> </child> <child> <name>child 2</name> </child> </parent> <parent> <name>parent 2</name> <child> <name>child 3</name> </child> </parent> </root> 

Code:

 declare @Child table ( ParentID int primary key, Child xml ); merge Parent as P using ( select TXvalue('(name/text())[1]', 'varchar(10)') as Name, TXquery('child') as Child from @XML.nodes('/root/parent') as T(X) ) as X on 0 = 1 when not matched then insert (Name) values (X.Name) output inserted.ParentID, X.Child into @Child; insert into Child(Name, ParentID) select TXvalue('(name/text())[1]', 'varchar(max)'), C.ParentID from @Child as C cross apply C.Child.nodes('/child') as T(X); 

SQL Fiddle

Toujours, parce que les sliders sont mauvais!

Je suppose que vous avez un moyen de lier les loggings enfants au parent à partir du file source. Je suppose également que vous insérez en bloc à partir d'un file XML, où la table enfant est représentée en tant que nœuds enfants dans le file XML? Si vous pouvez nous donner un exemple du XML que vous essayez de traiter, ce serait une aide précieuse. Pour l'instant, supposons que votre XML ressemble un peu à ceci:

 <root> <parent> <num>1</num> <name>P1</name> <children> <child> <num>1</num> <name>C1</name> </child> ... 

Votre table parent inclura une parent_key :

 DECLARE @parent TABLE ( num INT, parent_name VARCHAR(100), parent_key INT ) 

et la table enfant aura ses propres champs, plus l'élément d'identification du parent:

 DECLARE @child TABLE ( num INT, child_name VARCHAR(100), parent_num INT ) 

La table parent est remplie, ce qui est assez facile, donc je ne vais pas inclure un exemple de cela. Laissez le champ parent_key comme NULL, donc vous ne remplissez que les valeurs que vous connaissez.

La table enfant est remplie avec

 INSERT INTO @child SELECT * FROM OpenXML(@iDoc, '/root/parent/children/child', 2) WITH ( num INT, name VARCHAR(100), parent_num INT AS '../../num' ) 

Insérez dans votre table parent, comme d'habitude:

 INSERT INTO #parent (num, parent_name) SELECT num, parent_name FROM @parent ORDER BY num 

Ensuite, en utilisant ROW_NUMBER et @@ IDENTITY, vous pouvez dériver les valeurs d'identité utilisées pour les keys primaires parentes.

 ;WITH cte1 AS (SELECT COUNT(*) AS cnt FROM @parent), cte2 AS (SELECT ROW_NUMBER() OVER (ORDER BY num) AS row_num, num FROM #parent) UPDATE p SET parent_key = @@IDENTITY - cte1.cnt + cte2.row_num FROM @parent p, cte1, cte2 WHERE p.num = cte2.num 

De là, vous devriez aller bien.