Jag antar att Blocks.BlockID , Elevations.ElevationID , Floors.FloorID , Panels.PanelID är primärnycklar och autogenererad IDENTITY .
- Ett
Blockhar mångaElevations. - En
Elevationhar mångaFloors. - En
Floorhar 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
;