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.