2009-09-03 5 views
1

Disons que j'ai deux tablesComment puis-je faire plusieurs inserts sans un curseur

tblA ( tableAID INT IDENTITY (1,1), foo VARCHAR (100))

tblB ( tableBID INTIDENTITY (1,1), tableAID INT, bar varchar (100))

tblB.tableAID est un FK à tblA.

Je veux insérer un groupe d'enregistrements (tirés d'une autre table du système) dans cette paire de tables. J'ai besoin de savoir quel est l'identifiant de l'insertion dans tblA avant de pouvoir l'insérer dans tblB.

Y at-il un moyen de le faire sans le traiter ligne par ligne?

Répondre

3

Dans SQL Server 2005 et plus tard, vous pouvez utiliser la clause SORTIE pour passer les nouvelles valeurs clés dans une deuxième table:

INSERT INTO T ... 
OUTPUT PrimaryKeycol, otherValues INTO ChildTable; 

Autres possibilies existent dans SQL Server 2008 avec "composable DML" et l'instruction MERGE.

Ajouté en réponse à un commentaire:

create table T(i int identity(1,1), j int, k int default -1); 
go 

merge into T using (values (1), (2)) as U(j) 
on U.j = T.j 
when not matched then insert (j) values (j) 
output inserted.i, inserted.k; 
go 

drop table T; 
+0

C'est le plus proche de ce que je cherchais.Le seul inconvénient est que la clause OUTPUT ne peut accéder qu'aux colonnes spécifiées dans la table cible, ce qui est une sorte de problème de poule et d'oeuf - si j'avais quelque chose d'unique que j'insérais dans la table cible, je pourrais simplement me joindre à la table cible pour obtenir l'ID inséré. Pourtant, j'accepte votre réponse parce qu'elle m'a appris quelque chose de nouveau. – stannius

+2

Conseil: Si vous utilisez MERGE au lieu de INSERT, vous pouvez inclure des colonnes non mentionnées dans la clause OUTPUT. Je vais ajouter un exemple à ma réponse. –

0

Pouvez-vous utiliser une table temporaire?

DECLARE @t TABLE (foo, int, ba VARCHAR(50)) 
INSERT INTO @t (foo, bar) SELECT foo, bar FROM your_other_table 
ALTER TABLE @t ADD id_a INT IDENTITY(1, 1) 

Vous devez utiliser SET IDENTITY_INSERT OFF pour faire

Peut-être que vous voulez reseed votre table pour faire une insertion correcte tandis que la table est en production.

DBCC CHECKIDENT 'tblA' RESEED, newValue 
+0

La table cible contient déjà des données, donc je dois obtenir les valeurs d'identité à partir de là. De plus, le système fonctionnera donc je ne peux pas faire MAX (id) +1. – stannius

+0

Je viens de mettre plus d'infos ... Expliquer les trucs RESEED ... peut-être qu'il peut être utile pour vous –

0

Si l'on suppose que ce que vous demandez vraiment est de savoir comment éviter de multiples allers-retours au serveur, puis d'une façon est d'écrire une procédure stockée qui fait les deux inserts, et utilise

Set @Pk = Scope_Identity() 

après la première insertion pour obtenir la valeur d'identité créée pour cette première insertion, puis utilise cette valeur @Pk pour la deuxième insertion.

est ici un exemple simple

Create Procedure SaveEmployee 
@Name varChar(30), 
@DivId Int, 
@HomePhoneNumber VarChar(12), 
@FaxNumber VarChar(12) 
As 
Set NoCount On 
Declare @Pk Integer 


    Insert Employees(Name, Divisionid) 
    Values(@Name, @DivId) 
    Set @Pk = Scope_Identity() 
    -- ------------------------------------------------ 
    Insert PhoneNums(EmployeeId, PhoneType, PhoneNumber) 
    Values(@Pk, 'Home', @HomePhoneNumber) 
    -- ------------------------------------------------ 
    Insert PhoneNums(EmployeeId, PhoneType, PhoneNumber) 
    Values(@Pk, 'Fax', @FaxNumber) 

    Return 1 
+0

En fait, le script est en cours d'exécution sur le serveur. Ce que j'essaie d'éviter, c'est un curseur. – stannius

0

Il est probablement passé le point où il est utile, mais cela souligne une difficulté inhérente à l'utilisation des clés primaires de substitution, et en particulier avec les utilisant comme clés étrangères autres tables. Si vos relations sont définies à l'aide de clés naturelles, vous savez dès le début quelles valeurs insérer.

+0

Je n'ai pas défini le schéma, et ceux qui contrôlent le schéma sont dans le camp de substitution. Quoi qu'il en soit, je ne sais pas quelle clé naturelle serait appropriée pour la table en question - le seul candidat potentiel userId + title, mais il n'y a pas de règle de gestion selon laquelle les titres doivent être uniques, et on contredit probablement la base de données règles, pas l'inverse, non? – stannius

Questions connexes