Ich gehe davon aus, dass Blocks.BlockID
, Elevations.ElevationID
, Floors.FloorID
, Panels.PanelID
sind Primärschlüssel und automatisch generierte IDENTITY
.
- Ein
Block
hat vieleElevations
. - Eine
Elevation
hat vieleFloors
. - Eine
Floor
hat vielePanels
.
Ich würde MERGE
verwenden
mit OUTPUT
Klausel.
MERGE
kann INSERT
, UPDATE
und DELETE
Zeilen. In diesem Fall brauchen wir nur INSERT
.
1=0
ist immer falsch, also NOT MATCHED BY TARGET
Teil wird immer ausgeführt. Im Allgemeinen könnte es andere Branches geben, siehe docs.WHEN MATCHED
wird normalerweise zum UPDATE
verwendet;WHEN NOT MATCHED BY SOURCE
wird normalerweise zum DELETE
verwendet , aber wir brauchen sie hier nicht.
Diese verschlungene Form von MERGE
entspricht einfach INSERT
, aber im Gegensatz zu einfachem INSERT
sein OUTPUT
-Klausel ermöglicht es, auf die Spalten zu verweisen, die wir benötigen. Sie ermöglicht das Abrufen von Spalten sowohl aus Quell- als auch aus Zieltabellen und spart so eine Zuordnung zwischen alten vorhandenen IDs und neuen IDs, die von IDENTITY
generiert wurden .
Blockieren
Kopiere einen gegebenen Block
und merken Sie sich die ID
des neuen Block
.Wir können einfach INSERT
verwenden und SCOPE_IDENTITY
hier, weil BlockID
ist Primärschlüssel und es kann nur eine Zeile eingefügt werden.
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öhen
Kopieren Sie Elevations
vom alten Block
und weise sie dem neuen Block
zu .Denken Sie an die Zuordnung zwischen alten IDs
und frisch generierte IDs
in @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)
;
Böden
Kopieren Sie Floors
mit Mapping zwischen alter und neuer ElevationID
.Denken Sie an die Zuordnung zwischen alten IDs
und frisch generierte IDs
in @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)
;
Panels
Kopieren Sie Panels
mit Mapping zwischen alter und neuer FloorID
.Dies ist die letzte Detailebene, also können wir einfach INSERT
verwenden und denken Sie nicht an die Zuordnung von 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
;