Supongo que Blocks.BlockID
, Elevations.ElevationID
, Floors.FloorID
, Panels.PanelID
son claves primarias y IDENTITY
generadas automáticamente .
- Un
Block
tiene muchasElevations
. - Una
Elevation
tiene muchosFloors
. - Un
Floor
tiene 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
;