2009-11-24 8 views
4

Ok, cela va sembler étrange, mais pouvez-vous faire un insert dans une jointure de deux tables?Insertion Transact-SQL dans deux tables à la fois?

J'ai une table A et une table B avec une clé étrangère à A. Maintenant, je veux copier plusieurs enregistrements de la table A dans une requête + une copie des enregistrements dans la table B avec la clé étrangère pour les enregistrements en cours de copie dans le tableau A (mais en tant que clé étrangère les nouvelles identités).

J'espère que quelqu'un me comprend. Mon autre option est d'utiliser un curseur mais si possible je voudrais éviter cela.

+0

Un exemple, s'il vous plaît. Copie d'où à où? Pseudo-code fera l'affaire. –

+0

Ok, va ajouter un exemple demain. –

Répondre

3

Une autre option est deux requêtes.

Copiez d'abord les enregistrements avec les clés primaires, puis copiez les enregistrements avec les clés étrangères.

0

Pls pas ... curseurs

Vous pouvez simplement utiliser un déclencheur INSERT sur A qui insère dans B. Vous suffit d'exécuter la requête sur A, le déclencheur tireraient pour chaque insert.

1

Voici un exemple, si vous essayez de "insérer dans les deux tables" à la fois.

view_model_01

D'abord une certaine préparation, créer des tables etc ..

CREATE TABLE Tbl_A (
    Tbl_A_ID int NOT NULL 
        PRIMARY KEY identity(1,1) 
    ,A1 varchar(20) 
    ,A2 varchar(20) 
    ,A3 varchar(20) 
    ) 
GO 

CREATE TABLE Tbl_B (
    Tbl_B_ID int NOT NULL 
        PRIMARY KEY identity(1,1) 
    ,Tbl_A_ID int NOT NULL 
    ,B1 varchar(20) 
    ,B2 varchar(20) 
    ) 
GO  

ALTER TABLE TBL_B 
ADD CONSTRAINT FK1_B FOREIGN KEY (Tbl_A_ID) REFERENCES TBL_A (Tbl_A_ID) 
GO 

maintenant une vue sur ces deux tableaux

CREATE VIEW vAB (A1, A2, A3, B1, B2) 
AS 
    SELECT a.A1, a.A2, a.A3, b.B1, b.B2 
    FROM Tbl_A AS a 
     JOIN Tbl_B AS b ON a.Tbl_A_ID = b.Tbl_a_ID 
GO 

et un lieu d'insertion déclenchement sur la vue

CREATE TRIGGER trigAB 
ON vAB INSTEAD OF INSERT 
AS 
BEGIN 
    SET NOCOUNT ON 
    DECLARE @aid int 

    SET @aid = coalesce((SELECT max(Tbl_A_ID) FROM Tbl_A),0) 
    SET IDENTITY_INSERT Tbl_A ON 
    ; 
    WITH abc AS(
    SELECT A1, A2, A3, B1, B2, row_number() OVER(ORDER BY a1,a2,a3,b1,b2) AS rn 
    FROM INSERTED 
    )  
    INSERT INTO Tbl_A (Tbl_A_ID, A1, A2, A3) 
     SELECT @aid + [rn], A1, A2, A3 FROM abc 

    SET IDENTITY_INSERT Tbl_A OFF 

    ; 
    WITH abc AS(
    SELECT A1, A2, A3, B1, B2, row_number() OVER(ORDER BY a1,a2,a3,b1,b2) AS rn 
    FROM INSERTED 
    )  
    INSERT INTO Tbl_B (Tbl_A_ID, B1, B2) 
     SELECT @aid + [rn], B1, B2 FROM abc 

END 

Alors maintenant, il est possible de:

INSERT INTO vAB (a1, a2, a3, b1, b2) 
VALUES 
('a1_1', 'a2_1', 'a3_1', 'b1_1', 'b2_1') 
,('a1_2', 'a2_2', 'a3_2', 'b1_2', 'b2_2')   
,('a1_3', 'a2_3', 'a3_3', 'b1_3', 'b2_3')   
,('a1_4', 'a2_4', 'a3_4', 'b1_4', 'b2_4')   
,('a1_5', 'a2_5', 'a3_5', 'b1_5', 'b2_5')  

Vérifiez avec:

SELECT * FROM vAB ; 
1

Ok, cela sonnera bizarre, mais pouvez-vous faire un insert dans une jointure de deux tables?

La réponse courte est non; vous ne pouvez insérer que dans une table à la fois. La réponse la plus longue est que vous pouvez la contourner avec une vue ou des déclencheurs, mais si vous allez aussi loin, alors pourquoi ne pas simplement utiliser une procédure stockée (qui sera plus facile à écrire, à comprendre et à maintenir) ? Au lieu d'une seule instruction, du point de vue de la performance et de la fiabilité, il semble que ce que vous voulez vraiment faire soit d'utiliser une seule transaction. Il existe également des techniques qui vous permettent de gérer des insertions à plusieurs lignes sans avoir recours à des curseurs.

Pour les détails de votre opération spécifique, il serait utile si vous pouviez poster un exemple de code.

Questions connexes