Możesz (ab) użyć MERGE
z OUTPUT klauzula.
MERGE może INSERT , UPDATE i DELETE wydziwianie. W naszym przypadku wystarczy tylko INSERT .1=0 jest zawsze fałszywe, więc NOT MATCHED BY TARGET część jest zawsze wykonywana.Ogólnie rzecz biorąc, mogą istnieć inne gałęzie, zobacz docs.WHEN MATCHED jest zwykle używany do UPDATE;WHEN NOT MATCHED BY SOURCE jest zwykle używany do DELETE , ale nie potrzebujemy ich tutaj.
Ta zawiła forma MERGE jest odpowiednikiem prostego INSERT , ale w przeciwieństwie do prostego INSERT jego OUTPUT klauzula pozwala na odwołanie się do kolumn, których potrzebujemy. Pozwala na pobranie kolumn zarówno z tabel źródłowych, jak i docelowych, zapisując w ten sposób mapowanie między starymi i nowymi identyfikatorami.
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])
;
Jeśli chodzi o twoją aktualizację i poleganie na kolejności generowanej IDENTITY wartości.
W prostym przypadku, gdy [dbo].[Test] ma IDENTITY kolumna, a następnie INSERT z ORDER BY będzie zagwarantować, że wygenerowana IDENTITY wartości byłyby w określonej kolejności. Zobacz punkt 4 w Gwarancje zamawiania w SQL Server . Pamiętaj, że nie gwarantuje to fizycznej kolejności wstawianych wierszy, ale gwarantuje kolejność, w jakiej IDENTITY wartości są generowane.
INSERT INTO [dbo].[Test] ([Data])
SELECT [Data]
FROM @Old
ORDER BY [RowID]
Ale kiedy używasz OUTPUT klauzula:
INSERT INTO [dbo].[Test] ([Data])
OUTPUT inserted.[ID] INTO @New
SELECT [Data]
FROM @Old
ORDER BY [RowID]
wiersze w OUTPUT strumień nie jest uporządkowany. A przynajmniej, ściśle mówiąc, ORDER BY w zapytaniu dotyczy podstawowego INSERT operacji, ale nic tam nie mówi, jaka jest kolejność OUTPUT . Więc nie próbowałbym na tym polegać. Użyj MERGE lub dodaj dodatkową kolumnę, aby jawnie przechowywać mapowanie między identyfikatorami.