Předpokládám, že Blocks.BlockID
, Elevations.ElevationID
, Floors.FloorID
, Panels.PanelID
jsou primární klíče a automaticky generované IDENTITY
.
- Jeden
Block
má mnohoElevations
. - Jedna
Elevation
má mnohoFloors
. - Jedno
Floor
má mnohoPanels
.
Použil bych MERGE
s OUTPUT
klauzule.
MERGE
může INSERT
, UPDATE
a DELETE
řádky. V tomto případě potřebujeme pouze INSERT
.
1=0
je vždy nepravda, takže NOT MATCHED BY TARGET
část se vždy provede. Obecně mohou existovat další větve, viz dokumenty.WHEN MATCHED
se obvykle používá k UPDATE
;WHEN NOT MATCHED BY SOURCE
se obvykle používá k DELETE
, ale tady je nepotřebujeme.
Tato spletitá forma MERGE
je ekvivalentní jednoduchému INSERT
,ale na rozdíl od jednoduchého INSERT
jeho OUTPUT
klauzule umožňuje odkazovat na sloupce, které potřebujeme. Umožňuje načíst sloupce ze zdrojových i cílových tabulek, čímž se ukládá mapování mezi starými existujícími ID a novými ID generovanými IDENTITY
.
Blokovat
Zkopírujte jeden daný Block
a zapamatujte si IDs
nového Block
.Můžeme použít jednoduchý INSERT
a SCOPE_IDENTITY
zde, protože BlockID
je primární klíč a lze do něj vložit pouze jeden řádek.
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();
Výšky
Zkopírujte Elevations
ze starého Block
a přiřadit je k novému Block
.Pamatujte si na mapování mezi starými IDs
a čerstvě vygenerovaná IDs
v @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)
;
Podlaží
Zkopírujte Floors
pomocí mapování mezi starým a novým ElevationID
.Pamatujte si na mapování mezi starými IDs
a čerstvě vygenerovaná IDs
v @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)
;
Panely
Zkopírujte Panels
pomocí mapování mezi starým a novým FloorID
.Toto je poslední úroveň detailů, takže můžeme použít jednoduchý INSERT
a nepamatujte si mapování 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
;