Ich gehe davon aus, dass Blocks.BlockID , Elevations.ElevationID , Floors.FloorID , Panels.PanelID sind Primärschlüssel und automatisch generierte IDENTITY .
- Ein
Blockhat vieleElevations. - Eine
Elevationhat vieleFloors. - Eine
Floorhat 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
;