Zakładam, że Blocks.BlockID , Elevations.ElevationID , Floors.FloorID , Panels.PanelID są kluczami podstawowymi i automatycznie generowanymi IDENTITY .
- Jeden
Blockma wieleElevations. - Jedna
Elevationma wieleFloors. - Jedno
Floorma wielePanels.
Użyłbym MERGE
z OUTPUT klauzula.
MERGE może INSERT , UPDATE i DELETE rows.W tym przypadku potrzebujemy tylko INSERT .
1=0 jest zawsze fałszywe, więc NOT MATCHED BY TARGET część jest zawsze wykonywana.Ogólnie rzecz biorąc, mogą istnieć inne gałęzie, zobacz docs.WHEN MATCHED jest zwykle używany do UPDATE;WHEN NOT MATCHED BY SOURCE jest zwykle używany do DELETE , ale nie potrzebujemy ich tutaj.
Ta zawiła forma MERGE jest odpowiednikiem prostego INSERT , ale w przeciwieństwie do prostego INSERT jego OUTPUT klauzula pozwala na odwołanie się do potrzebnych nam kolumn. Pozwala na pobranie kolumn zarówno z tabel źródłowych, jak i docelowych, zapisując w ten sposób mapowanie między starymi istniejącymi identyfikatorami a nowymi identyfikatorami wygenerowanymi przez IDENTITY .
Zablokuj
Skopiuj jeden podany Block i zapamiętaj ID nowego Block .Możemy użyć prostego INSERT i SCOPE_IDENTITY tutaj, ponieważ BlockID jest kluczem podstawowym i można wstawić tylko jeden wiersz.
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();
Elewacje
Skopiuj Elevations ze starego Block i przypisz je do nowego Block .Pamiętaj mapowanie między starymi IDs i świeżo wygenerowane IDs w @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)
;
Podłogi
Skopiuj Floors za pomocą mapowania między starym i nowym ElevationID .Pamiętaj mapowanie między starymi IDs i świeżo wygenerowane IDs w @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)
;
Panele
Skopiuj Panels używając mapowania między starym i nowym FloorID .To jest ostatni poziom szczegółów, więc możemy użyć prostego INSERT i nie przejmuj się mapowaniem 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
;