Ik neem aan dat Blocks.BlockID , Elevations.ElevationID , Floors.FloorID , Panels.PanelID zijn primaire sleutels en automatisch gegenereerde IDENTITY .
- Eén
Blockheeft veelElevations. - Eén
Elevationheeft veelFloors. - Eén
Floorheeft veelPanels.
Ik zou MERGE gebruiken
met OUTPUT clausule.
MERGE kan INSERT , UPDATE en DELETE rijen.In dit geval hebben we alleen INSERT . nodig .
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 wordt opgeslagen tussen oude bestaande ID's en nieuwe ID's gegenereerd door IDENTITY .
Blokkeren
Kopieer een gegeven Block en onthoud de ID van het nieuwe Block .We kunnen eenvoudige INSERT . gebruiken en SCOPE_IDENTITY hier, omdat BlockID is de primaire sleutel en er kan slechts één rij worden ingevoegd.
DECLARE @blockToCopy int = 1;
DECLARE @VarNewBlockID int;
INSERT INTO Blocks
(ProjectID
,BlockName
,BlockDescription)
SELECT
ProjectID
,'NewNameTest'
,'NewDescTest'
FROM Blocks
WHERE Blocks.BlockID = @blockToCopy
;
SET @VarNewBlockID = SCOPE_IDENTITY();
Verhogingen
Kopieer Elevations van oud Block en wijs ze toe aan het nieuwe Block .Denk aan de toewijzing tussen oude IDs en vers gegenereerde IDs in @MapElevations .
DECLARE @MapElevations TABLE(OldElevationID int, NewElevationID int);
MERGE INTO Elevations
USING
(
SELECT
ElevationID
,@VarNewBlockID AS BlockID
,ElevationName
,ElevationDescription
FROM Elevations
WHERE Elevations.BlockID = @blockToCopy
) AS Src
ON 1 = 0
WHEN NOT MATCHED BY TARGET THEN
INSERT
(BlockID
,ElevationName
,ElevationDescription)
VALUES
(Src.BlockID
,Src.ElevationName
,Src.ElevationDescription)
OUTPUT
Src.ElevationID AS OldElevationID
,inserted.ElevationID AS NewElevationID
INTO @MapElevations(OldElevationID, NewElevationID)
;
Vloeren
Kopieer Floors met behulp van mapping tussen oud en nieuw ElevationID .Denk aan de toewijzing tussen oude IDs en vers gegenereerde IDs in @MapFloors .
DECLARE @MapFloors TABLE(OldFloorID int, NewFloorID int);
MERGE INTO Floors
USING
(
SELECT
Floors.FloorID
,M.NewElevationID AS ElevationID
,Floors.FloorName
,Floors.FloorDescription
FROM
Floors
INNER JOIN Elevations ON Elevations.ElevationID = Floors.ElevationID
INNER JOIN @MapElevations AS M ON M.OldElevationID = Elevations.ElevationID
WHERE Elevations.BlockID = @blockToCopy
) AS Src
ON 1 = 0
WHEN NOT MATCHED BY TARGET THEN
INSERT
(ElevationID
,FloorName
,FloorDescription)
VALUES
(Src.ElevationID
,Src.FloorName
,Src.FloorDescription)
OUTPUT
Src.FloorID AS OldFloorID
,inserted.FloorID AS NewFloorID
INTO @MapFloors(OldFloorID, NewFloorID)
;
Panelen
Kopieer Panels met behulp van mapping tussen oud en nieuw FloorID .Dit is het laatste detailniveau, dus we kunnen eenvoudig INSERT . gebruiken en denk niet aan de toewijzing van IDs .
INSERT INTO Panels
(FloorID
,PanelName
,PanelDescription)
SELECT
M.NewFloorID
,Panels.PanelName
,Panels.PanelDescription
FROM
Panels
INNER JOIN Floors ON Floors.FloorID = Panels.FloorID
INNER JOIN Elevations ON Elevations.ElevationID = Floors.ElevationID
INNER JOIN @MapFloors AS M ON M.OldFloorID = Floors.FloorID
WHERE Elevations.BlockID = @blockToCopy
;