Jag antar att Blocks.BlockID
, Elevations.ElevationID
, Floors.FloorID
, Panels.PanelID
är primärnycklar och autogenererad IDENTITY
.
- Ett
Block
har mångaElevations
. - En
Elevation
har mångaFloors
. - En
Floor
har mångaPanels
.
Jag skulle använda MERGE
med OUTPUT
klausul.
MERGE
kan INSERT
, UPDATE
och DELETE
rows.I det här fallet behöver vi bara INSERT
.
1=0
är alltid falsk, så koden NOT MATCHED BY TARGET
del exekveras alltid. I allmänhet kan det finnas andra grenar, se dokument.WHEN MATCHED
används vanligtvis för att UPDATE
;WHEN NOT MATCHED BY SOURCE
används vanligtvis för att DELETE
, men vi behöver dem inte här.
Denna invecklade form av MERGE
motsvarar enkel INSERT
, men till skillnad från enkla INSERT
dess OUTPUT
klausulen gör det möjligt att referera till de kolumner som vi behöver. Den gör det möjligt att hämta kolumner från både käll- och destinationstabeller, vilket sparar en mappning mellan gamla befintliga ID:n och nya ID:n genererade av IDENTITY
.
Blockera
Kopiera ett givet Block
och kom ihåg ID
av det nya Block
.Vi kan använda enkla INSERT
och SCOPE_IDENTITY
här, eftersom BlockID
är primärnyckel och endast en rad kan infogas.
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();
Höjder
Kopiera Elevations
från gamla Block
och tilldela dem till det nya Block
.Kom ihåg mappningen mellan gamla IDs
och nyligen genererade IDs
i @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)
;
Golv
Kopiera Floors
med hjälp av mappning mellan gammalt och nytt ElevationID
.Kom ihåg mappningen mellan gamla IDs
och nyligen genererade IDs
i @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)
;
Paneler
Kopiera Panels
med hjälp av mappning mellan gammalt och nytt FloorID
.Detta är den sista detaljnivån, så vi kan använda enkla INSERT
och kom inte ihåg mappningen av 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
;