Você pode (ab) usar
MERGE
com OUTPUT
cláusula. MERGE
pode INSERT
, UPDATE
e DELETE
linhas. No nosso caso, precisamos apenas INSERT
.1=0 é sempre falso, então NOT MATCHED BY TARGET
parte é sempre executada. Em geral, pode haver outras ramificações, veja docs.WHEN MATCHED
geralmente é usado para UPDATE
;WHEN NOT MATCHED BY SOURCE
é normalmente usado para DELETE
, mas não precisamos deles aqui. Esta forma complicada de
MERGE
é equivalente ao simples INSERT
,mas ao contrário do simples INSERT
sua OUTPUT
A cláusula permite fazer referência às colunas que precisamos. Permite recuperar colunas das tabelas de origem e destino, salvando assim um mapeamento entre os IDs antigos e novos. 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])
;
Em relação à sua atualização e contando com a ordem de
IDENTITY
gerada valores. No caso simples, quando
[dbo].[Test]
tem IDENTITY
coluna e, em seguida, INSERT
com ORDER BY
vai garantir que a IDENTITY
gerada valores estariam na ordem especificada. Consulte o ponto 4 em Garantias de pedidos no SQL Server . Lembre-se, ele não garante a ordem física das linhas inseridas, mas garante a ordem em que IDENTITY
valores são gerados. INSERT INTO [dbo].[Test] ([Data])
SELECT [Data]
FROM @Old
ORDER BY [RowID]
Mas, quando você usa o
OUTPUT
cláusula:INSERT INTO [dbo].[Test] ([Data])
OUTPUT inserted.[ID] INTO @New
SELECT [Data]
FROM @Old
ORDER BY [RowID]
as linhas no
OUTPUT
fluxo não são ordenados. Pelo menos, estritamente falando, ORDER BY
na consulta se aplica ao INSERT
principal operação, mas não há nada lá que diga qual é a ordem do OUTPUT
. Então, eu não tentaria confiar nisso. Ou use MERGE
ou adicione uma coluna extra para armazenar explicitamente o mapeamento entre os IDs.