U kunt (ab)gebruiken MERGE
met OUTPUT
clausule.
MERGE
kan INSERT
, UPDATE
en DELETE
rijen. In ons geval hoeven we alleen INSERT
.1=0 is altijd onwaar, dus de NOT MATCHED BY TARGET
deel wordt altijd uitgevoerd. In het algemeen kunnen er andere branches zijn, zie docs.WHEN MATCHED
wordt meestal gebruikt om UPDATE
;WHEN NOT MATCHED BY SOURCE
wordt meestal gebruikt om DELETE
, maar we hebben ze hier niet nodig.
Deze ingewikkelde vorm van MERGE
is gelijk aan eenvoudig INSERT
,maar in tegenstelling tot eenvoudig INSERT
zijn OUTPUT
clausule maakt het mogelijk om te verwijzen naar de kolommen die we nodig hebben. Hiermee kunnen kolommen worden opgehaald uit zowel bron- als doeltabellen, waardoor een toewijzing tussen oude en nieuwe ID's wordt opgeslagen.
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])
;
Met betrekking tot uw update en vertrouwend op de volgorde van gegenereerde IDENTITY
waarden.
In het eenvoudige geval, wanneer [dbo].[Test]
heeft IDENTITY
kolom, dan INSERT
met ORDER BY
zal garanderen dat de gegenereerde IDENTITY
waarden zouden in de opgegeven volgorde staan. Zie punt 4 in Bestelgaranties in SQL Server . Let wel, het garandeert niet de fysieke volgorde van ingevoegde rijen, maar het garandeert de volgorde waarin IDENTITY
waarden worden gegenereerd.
INSERT INTO [dbo].[Test] ([Data])
SELECT [Data]
FROM @Old
ORDER BY [RowID]
Maar wanneer u de OUTPUT
. gebruikt clausule:
INSERT INTO [dbo].[Test] ([Data])
OUTPUT inserted.[ID] INTO @New
SELECT [Data]
FROM @Old
ORDER BY [RowID]
de rijen in de OUTPUT
stream zijn niet besteld. Strikt genomen tenminste, ORDER BY
in de zoekopdracht is van toepassing op de primaire INSERT
operatie, maar er is niets dat zegt wat de volgorde is van de OUTPUT
. Dus daar zou ik niet op proberen te vertrouwen. Gebruik ofwel MERGE
of voeg een extra kolom toe om de toewijzing tussen ID's expliciet op te slaan.