Je suppose que Blocks.BlockID , Elevations.ElevationID , Floors.FloorID , Panels.PanelID sont des clés primaires et IDENTITY généré automatiquement .
- Un
Blocka de nombreusesElevations. - Une
Elevationa plusieursFloors. - Un
Floora de nombreuxPanels.
J'utiliserais MERGE
avec OUTPUT clause.
MERGE peut INSERT , UPDATE et DELETE rows. Dans ce cas, nous n'avons besoin que de INSERT .
1=0 est toujours faux, donc le NOT MATCHED BY TARGET part est toujours exécutée.En général, il pourrait y avoir d'autres branches, voir docs.WHEN MATCHED est généralement utilisé pour UPDATE;WHEN NOT MATCHED BY SOURCE est généralement utilisé pour DELETE , mais nous n'en avons pas besoin ici.
Cette forme alambiquée de MERGE équivaut à un simple INSERT , mais contrairement au simple INSERT sa OUTPUT La clause permet de faire référence aux colonnes dont nous avons besoin. Elle permet de récupérer les colonnes des tables source et destination, économisant ainsi un mappage entre les anciens identifiants existants et les nouveaux identifiants générés par IDENTITY .
Bloquer
Copiez un Block donné et mémorisez l'IDs du nouveau Block .Nous pouvons utiliser de simples INSERT et SCOPE_IDENTITY ici, car BlockID est la clé primaire et une seule ligne peut être insérée.
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();
Altitudes
Copier Elevations de l'ancien Block et affectez-les au nouveau Block .Mémoriser le mappage entre les anciens IDs et des IDs fraîchement générés dans @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)
;
Étages
Copier Floors en utilisant le mappage entre l'ancien et le nouveau ElevationID .Mémoriser le mappage entre les anciens IDs et des IDs fraîchement générés dans @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)
;
Panneaux
Copier Panels en utilisant le mappage entre l'ancien et le nouveau FloorID .Ceci est le dernier niveau de détails, nous pouvons donc utiliser de simples INSERT et ne vous souvenez pas du mappage des 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
;