Можете (зло) да използвате 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
или добавете допълнителна колона, за да съхраните изрично съпоставянето между идентификаторите.