Presumo che Blocks.BlockID
, Elevations.ElevationID
, Floors.FloorID
, Panels.PanelID
sono chiavi primarie e IDENTITY
generati automaticamente .
- Un
Block
ha molteElevations
. - Un
Elevation
ha moltiFloors
. - Un
Floor
ha moltiPanels
.
Userei MERGE
con OUTPUT
clausola.
MERGE
può INSERT
, UPDATE
e DELETE
righe. In questo caso abbiamo solo bisogno di INSERT
.
1=0
è sempre falso, quindi NOT MATCHED BY TARGET
parte viene sempre eseguita. In generale, potrebbero esserci altri rami, vedere docs.WHEN MATCHED
è solitamente usato per UPDATE
;WHEN NOT MATCHED BY SOURCE
di solito è usato per DELETE
, ma non ne abbiamo bisogno qui.
Questa forma contorta di MERGE
è equivalente al semplice INSERT
,ma a differenza del semplice INSERT
il suo OUTPUT
la clausola permette di fare riferimento alle colonne di cui abbiamo bisogno. Permette di recuperare colonne sia dalle tabelle di origine che da quelle di destinazione salvando così una mappatura tra i vecchi ID esistenti e i nuovi ID generati da IDENTITY
.
Blocca
Copia un dato Block
e ricorda il IDs
del nuovo Block
.Possiamo usare un semplice INSERT
e SCOPE_IDENTITY
qui, perché BlockID
è la chiave primaria e può essere inserita solo una riga.
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();
Prospettive
Copia Elevations
dal vecchio Block
e assegnali al nuovo Block
.Ricorda la mappatura tra i vecchi IDs
e IDs
appena generati 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)
;
Pavimenti
Copia Floors
utilizzando la mappatura tra il vecchio e il nuovo ElevationID
.Ricorda la mappatura tra i vecchi IDs
e IDs
appena generati 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)
;
Riquadri
Copia Panels
utilizzando la mappatura tra il vecchio e il nuovo FloorID
.Questo è l'ultimo livello di dettagli, quindi possiamo usare un semplice INSERT
e non ricordare la mappatura di 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
;