Supongo que Blocks.BlockID , Elevations.ElevationID , Floors.FloorID , Panels.PanelID son claves primarias y IDENTITY generadas automáticamente .
- Un
Blocktiene muchasElevations. - Una
Elevationtiene muchosFloors. - Un
Floortiene muchosPanels.
Usaría MERGE
con OUTPUT cláusula.
MERGE puede INSERT , UPDATE y DELETE filas. En este caso solo necesitamos INSERT .
1=0 siempre es falso, por lo que NOT MATCHED BY TARGET la parte siempre se ejecuta. En general, podría haber otras ramas, consulte los documentos. WHEN MATCHED generalmente se usa para UPDATE;WHEN NOT MATCHED BY SOURCE generalmente se usa para DELETE , pero no los necesitamos aquí.
Esta forma complicada de MERGE es equivalente al simple INSERT ,pero a diferencia del simple INSERT su OUTPUT permite hacer referencia a las columnas que necesitamos. Permite recuperar columnas de las tablas de origen y de destino, guardando así un mapeo entre los ID antiguos existentes y los ID nuevos generados por IDENTITY .
Bloquear
Copie un Block dado y recuerda el IDs del nuevo Block .Podemos usar INSERT simple y SCOPE_IDENTITY aquí, porque BlockID es clave principal y solo se puede insertar una fila.
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();
Elevaciones
Copiar Elevations del antiguo Block y asígnelos al nuevo Block .Recuerde el mapeo entre IDs antiguos y IDs recién generados en @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)
;
Pisos
Copiar Floors usando el mapeo entre el antiguo y el nuevo ElevationID .Recuerde el mapeo entre IDs antiguos y IDs recién generados en @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)
;
Paneles
Copiar Panels usando el mapeo entre el antiguo y el nuevo FloorID .Este es el último nivel de detalles, por lo que podemos usar INSERT simple y no recuerdes el mapeo de 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
;