2010-09-15 8 views
2

J'ai un scénario dans lequel j'ai une table parente qui a des relations «1 à plusieurs» avec deux ou trois tables. Ces tables enfant ont à nouveau des relations '1 à plusieurs' avec plus de tables, etc. Cela va jusqu'à 5 à 6 niveaux de hiérarchie. Maintenant, en fonction de la valeur de clé primaire unique de la table parente, je veux dupliquer toutes les informations qui s'y rapportent dans la base de données. J'ai écrit une procédure stockée qui utilise des curseurs et insère les lignes enfant une par une et définit de nouvelles valeurs de clé étrangère avec chaque insertion. Mais cela prend du temps car le nombre d'enregistrements dans les tables enfants est élevé.Duplication efficace des enregistrements dans tsql

Existe-t-il un autre moyen efficace de le faire?

Répondre

2

En SQL Server 2008:

CREATE TABLE t_parent (id INT NOT NULL PRIMARY KEY IDENTITY, value VARCHAR(100)) 
CREATE TABLE t_child (id INT NOT NULL PRIMARY KEY IDENTITY, parent INT NOT NULL, value VARCHAR(100)) 
CREATE TABLE t_grandchild (id INT NOT NULL PRIMARY KEY IDENTITY, child INT NOT NULL, value VARCHAR(100)) 

INSERT 
INTO t_parent (value) 
VALUES ('Parent 1') 

INSERT 
INTO t_parent (value) 
VALUES ('Parent 2') 

INSERT 
INTO t_child (parent, value) 
VALUES (1, 'Child 2') 

INSERT 
INTO t_child (parent, value) 
VALUES (2, 'Child 2') 

INSERT 
INTO t_grandchild (child, value) 
VALUES (1, 'Grandchild 1') 

INSERT 
INTO t_grandchild (child, value) 
VALUES (1, 'Grandchild 2') 

INSERT 
INTO t_grandchild (child, value) 
VALUES (2, 'Grandchild 3') 

DECLARE @tt TABLE (oid INT, nid INT) 

MERGE 
INTO t_parent 
USING (
     SELECT id, value 
     FROM t_parent 
     ) p 
ON  1 = 0 
WHEN NOT MATCHED THEN 
INSERT (value) 
VALUES (value) 
OUTPUT p.id, INSERTED.id 
INTO @tt; 

MERGE 
INTO t_child 
USING (
     SELECT c.id, p.nid, c.value 
     FROM @tt p 
     JOIN t_child c 
     ON  c.parent = p.oid 
     ) c 
ON  1 = 0 
WHEN NOT MATCHED THEN 
INSERT (parent, value) 
VALUES (nid, value) 
OUTPUT c.id, INSERTED.id 
INTO @tt; 

INSERT 
INTO t_grandchild (child, value) 
SELECT c.nid, gc.value 
FROM @tt c 
JOIN t_grandchild gc 
ON  gc.child = c.oid 

Dans les versions antérieures de SQL Server, vous devrez faire un SELECT suivi d'un INSERT pour découvrir les nouvelles valeurs de la PRIMARY KEY.

+0

Merci Quassnoi, j'utilise SQL 05. Pouvez-vous donner un exemple d'utilisation OUTPUT dans un INSERT. Je veux des identifiants d'enregistrements nouvellement ajoutés. – Sami

1

Vous devrez insérer une table à la fois, mais vous pouvez le faire en insérant des ensembles au lieu de lignes si vous autorisez les valeurs FK dans les tables enfant du nouveau parent à être les mêmes que les valeurs FK de l'original parent.

Dites que vous avez une vue de votre table parente et dans votre sp vous limitez à la ligne à partir de laquelle copier (pk = 1, disons). Ensuite, insérez cette ligne dans la table parente en remplaçant PK = 2 par PK = 2.

Utilisez maintenant une deuxième vue de l'une des tables enfant. Dans votre sp, limitez l'ensemble des rangs à ceux avec PK = 1. A nouveau, insérez toutes ces lignes dans la même table enfant en remplaçant PK = 2 par la valeur du champ PK.

Questions connexes