Je suppose que Blocks.BlockID
, Elevations.ElevationID
, Floors.FloorID
, Panels.PanelID
sont des clés primaires et IDENTITY
généré automatiquement .
- Un
Block
a de nombreusesElevations
. - Une
Elevation
a plusieursFloors
. - Un
Floor
a 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
;