Zakładam, że Blocks.BlockID
, Elevations.ElevationID
, Floors.FloorID
, Panels.PanelID
są kluczami podstawowymi i automatycznie generowanymi IDENTITY
.
- Jeden
Block
ma wieleElevations
. - Jedna
Elevation
ma wieleFloors
. - Jedno
Floor
ma 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
;