Можете (зло) да използвате MERGE
с OUTPUT клауза.
MERGE може INSERT , UPDATE и DELETE редове. В нашия случай трябва само да INSERT .1=0 винаги е невярно, така че NOT MATCHED BY TARGET част винаги се изпълнява. По принцип може да има други разклонения, вижте документите.WHEN MATCHED обикновено се използва за UPDATE;WHEN NOT MATCHED BY SOURCE обикновено се използва за DELETE , но не ни трябват тук.
Тази сложна форма на MERGE е еквивалентен на обикновен INSERT , но за разлика от простия INSERT неговият OUTPUT клаузата позволява препращане към колоните, от които се нуждаем. Позволява извличане на колони както от таблици източник, така и от таблици местоназначение, като по този начин спестява съпоставяне между стари и нови идентификатори.
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])
;
Относно вашата актуализация и разчитане на реда на генерираните IDENTITY стойности.
В простия случай, когато [dbo].[Test] има IDENTITY колона, след което INSERT с ORDER BY ще гарантират, че генерираната IDENTITY стойностите ще бъдат в посочения ред. Вижте точка 4 в Гаранции за поръчки в SQL Server . Имайте предвид, че не гарантира физическия ред на вмъкнатите редове, но гарантира реда, в който IDENTITY се генерират стойности.
INSERT INTO [dbo].[Test] ([Data])
SELECT [Data]
FROM @Old
ORDER BY [RowID]
Но когато използвате OUTPUT клауза:
INSERT INTO [dbo].[Test] ([Data])
OUTPUT inserted.[ID] INTO @New
SELECT [Data]
FROM @Old
ORDER BY [RowID]
редовете в OUTPUT поток не са подредени. Поне, строго погледнато, ORDER BY в заявката се отнася за основния INSERT операция, но там няма нищо, което да казва какъв е редът на OUTPUT . Така че не бих се опитал да разчитам на това. Или използвайте MERGE или добавете допълнителна колона, за да съхраните изрично съпоставянето между идентификаторите.