Du kan (ab)bruge MERGE
med OUTPUT klausul.
MERGE kan INSERT , UPDATE og DELETE rækker. I vores tilfælde behøver vi kun at INSERT .1=0 er altid falsk, så NOT MATCHED BY TARGET del udføres altid. Generelt kan der være andre grene, se docs.WHEN MATCHED bruges normalt til at UPDATE;WHEN NOT MATCHED BY SOURCE bruges normalt til at DELETE , men vi har ikke brug for dem her.
Denne indviklede form for MERGE svarer til simpel INSERT , men i modsætning til simpel INSERT dens OUTPUT klausulen gør det muligt at henvise til de kolonner, vi har brug for. Det giver mulighed for at hente kolonner fra både kilde- og destinationstabeller og dermed gemme en kortlægning mellem gamle og nye ID'er.
MERGE INTO [dbo].[Test]
USING
(
SELECT [Data]
FROM @Old AS O
) AS Src
ON 1 = 0
WHEN NOT MATCHED BY TARGET THEN
INSERT ([Data])
VALUES (Src.[Data])
OUTPUT Src.ID AS OldID, inserted.ID AS NewID
INTO @New(ID, [OtherID])
;
Med hensyn til din opdatering og afhængig af rækkefølgen af genereret IDENTITY værdier.
I det simple tilfælde, når [dbo].[Test] har IDENTITY kolonne, derefter INSERT med ORDER BY vil garantere, at den genererede IDENTITY værdier ville være i den angivne rækkefølge. Se punkt 4 i Bestillingsgarantier i SQL Server . Husk, det garanterer ikke den fysiske rækkefølge af indsatte rækker, men det garanterer rækkefølgen, hvori IDENTITY værdier genereres.
INSERT INTO [dbo].[Test] ([Data])
SELECT [Data]
FROM @Old
ORDER BY [RowID]
Men når du bruger OUTPUT klausul:
INSERT INTO [dbo].[Test] ([Data])
OUTPUT inserted.[ID] INTO @New
SELECT [Data]
FROM @Old
ORDER BY [RowID]
rækkerne i OUTPUT stream er ikke bestilt. I det mindste strengt taget ORDER BY i forespørgslen gælder for den primære INSERT operation, men der er intet der, der siger, hvad rækkefølgen er af OUTPUT . Så det ville jeg ikke prøve at stole på. Brug enten MERGE eller tilføj en ekstra kolonne for at gemme tilknytningen mellem ID'er eksplicit.