Puis-je conserver les anciennes keys liées aux nouvelles keys lors d'une copy en SQL?

J'essaie de copyr un logging dans une table et de modifier quelques valeurs avec une procédure stockée dans SQL Server 2005. C'est simple, mais j'ai également besoin de copyr des relations dans d'autres tables avec les nouvelles keys primaires. Comme cette procédure est utilisée pour copyr des loggings par lots, j'ai trouvé difficile de stocker une relation entre les anciennes keys et les nouvelles keys. En ce moment, je saisis de nouvelles keys à partir de l'insertion de lot en utilisant OUTPUT INTO. ex:

INSERT INTO table (column1, column2,...) OUTPUT INSERTED.PrimaryKey INTO @TableVariable SELECT column1, column2,... 

Y a-t-il un moyen comme celui-ci d'insert facilement les anciennes keys en même time que j'insère de nouvelles keys (pour m'assurer d'avoir associé les bonnes touches correspondantes)?

Je sais que les sliders sont une option, mais je ne les ai jamais utilisés et je les ai seulement entendus référencés dans une histoire d'horreur. Je préférerais de beaucoup utiliser OUTPUT INTO, ou quelque chose comme ça.

Si vous devez suivre les anciennes et les nouvelles keys dans votre table temporaire, vous devez sortingcher et utiliser MERGE :

Configuration des données:

 create table T ( ID int IDENTITY(5,7) not null, Col1 varchar(10) not null ); go insert into T (Col1) values ('abc'),('def'); 

Et le rlocation de votre instruction INSERT :

 declare @TV table ( Old_ID int not null, New_ID int not null ); merge into T t1 using (select ID,Col1 from T) t2 on 1 = 0 when not matched then insert (Col1) values (t2.Col1) output t2.ID,inserted.ID into @TV; 

Et (en fait, doit être dans le même lot afin que vous puissiez accéder à la variable de table):

 select * from T; select * from @TV; 

Produit:

 ID Col1 5 abc 12 def 19 abc 26 def Old_ID New_ID 5 19 12 26 

La raison pour laquelle vous devez faire cela est à cause d'une limitation irritante sur la clause OUTPUT quand elle est utilisée avec INSERT – vous pouvez seulement accéder à la table inserted , pas aux tables qui pourraient faire partie d'un SELECT .


Connexes – Plus d'explications sur l'abus MERGE

INSERT instructions INSERT qui chargent des données dans des tables avec une colonne IDENTITY garantissent la génération des valeurs dans le même ordre que la clause ORDER BY du SELECT .

Si vous souhaitez que les valeurs IDENTITY soient atsortingbuées de manière séquentielle après la command dans la clause ORDER BY, créez une table contenant une colonne avec la propriété IDENTITY, puis exécutez une requête INSERT .. SELECT … ORDER BY pour remplir cette table .

De: Le comportement de la fonction IDENTITY lorsqu'il est utilisé avec des requêtes SELECT INTO ou INSERT .. SELECT contenant une clause ORDER BY

Vous pouvez utiliser ce fait pour faire correspondre votre ancien avec vos nouvelles valeurs d'identité. Commencez par collecter la list des keys primaires que vous avez l'intention de copyr dans une table temporaire. Vous pouvez également inclure vos valeurs de colonne modifiées si nécessaire:

 select PrimaryKey, Col1 --Col2... etc into #NewRecords from Table --where whatever... 

Ensuite, faites votre INSERT avec la clause OUTPUT pour capturer vos nouveaux identifiants dans la variable table:

 declare @TableVariable table ( New_ID int not null ); INSERT INTO #table (Col1 /*,Col2... ect.*/) OUTPUT INSERTED.PrimaryKey INTO @NewIds SELECT Col1 /*,Col2... ect.*/ from #NewRecords order by PrimaryKey 

En raison de l'instruction ORDER BY PrimaryKey , vous serez assuré que vos numéros New_ID seront générés dans le même ordre que le champ PrimaryKey des loggings copiés. Vous pouvez maintenant les faire correspondre par numéro de ligne ordonné par les valeurs d'ID. La requête suivante vous donnerait les parages:

 select PrimaryKey, New_ID from (select PrimaryKey, ROW_NUMBER() over (order by PrimaryKey) OldRow from #NewRecords ) PrimaryKeys join ( select New_ID, ROW_NUMBER() over (order by New_ID) NewRow from @NewIds ) New_IDs on OldRow = NewRow