Puede (ab) usar MERGE
con OUTPUT
cláusula.
MERGE
puede INSERT
, UPDATE
y DELETE
filas En nuestro caso solo necesitamos INSERT
.1=0 siempre es falso, por lo que NOT MATCHED BY TARGET
la parte siempre se ejecuta. En general, podría haber otras ramas, consulte los documentos. WHEN MATCHED
generalmente se usa para UPDATE
;WHEN NOT MATCHED BY SOURCE
generalmente se usa para DELETE
, pero no los necesitamos aquí.
Esta forma complicada de MERGE
es equivalente al simple INSERT
,pero a diferencia del simple INSERT
su OUTPUT
La cláusula permite hacer referencia a las columnas que necesitamos. Permite recuperar columnas de las tablas de origen y de destino, guardando así una asignación entre las ID antiguas y las nuevas.
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])
;
Con respecto a su actualización y confiando en el orden de IDENTITY
generado valores.
En el caso simple, cuando [dbo].[Test]
tiene IDENTITY
columna, luego INSERT
con ORDER BY
voluntad garantiza que la IDENTITY
generada los valores estarían en el orden especificado. Consulte el punto 4 en Garantías de pedidos en SQL Server . Eso sí, no garantiza el orden físico de las filas insertadas, pero garantiza el orden en que IDENTITY
se generan valores.
INSERT INTO [dbo].[Test] ([Data])
SELECT [Data]
FROM @Old
ORDER BY [RowID]
Pero, cuando usas OUTPUT
cláusula:
INSERT INTO [dbo].[Test] ([Data])
OUTPUT inserted.[ID] INTO @New
SELECT [Data]
FROM @Old
ORDER BY [RowID]
las filas en el OUTPUT
Las secuencias no están ordenadas. Al menos, estrictamente hablando, ORDER BY
en la consulta se aplica al INSERT
principal operación, pero no hay nada allí que diga cuál es el orden de la OUTPUT
. Por lo tanto, no trataría de confiar en eso. Usa MERGE
o agregue una columna adicional para almacenar la asignación entre ID explícitamente.