Ik neem aan dat Blocks.BlockID
, Elevations.ElevationID
, Floors.FloorID
, Panels.PanelID
zijn primaire sleutels en automatisch gegenereerde IDENTITY
.
- Eén
Block
heeft veelElevations
. - Eén
Elevation
heeft veelFloors
. - Eén
Floor
heeft 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
;