Jeg antager, at Blocks.BlockID
, Elevations.ElevationID
, Floors.FloorID
, Panels.PanelID
er primærnøgler og autogenereret IDENTITY
.
- Én
Block
har mangeElevations
. - Én
Elevation
har mangeFloors
. - Én
Floor
har mangePanels
.
Jeg ville bruge MERGE
med OUTPUT
klausul.
MERGE
kan INSERT
, UPDATE
og DELETE
rows.I dette tilfælde behøver vi kun INSERT
.
1=0
er altid falsk, så NOT MATCHED BY TARGET
del udføres altid. Generelt kan der være andre grene, se docs.WHEN MATCHED
bruges normalt til at UPDATE
;WHEN NOT MATCHED BY SOURCE
bruges normalt til at DELETE
, men vi har ikke brug for dem her.
Denne indviklede form for MERGE
svarer til simpel INSERT
, men i modsætning til simpel INSERT
dens OUTPUT
klausulen gør det muligt at henvise til de kolonner, vi har brug for. Det giver mulighed for at hente kolonner fra både kilde- og destinationstabeller og gemmer således en kortlægning mellem gamle eksisterende ID'er og nye ID'er genereret af IDENTITY
.
Bloker
Kopier en given Block
og husk ID
af den nye Block
.Vi kan bruge simpel INSERT
og SCOPE_IDENTITY
her, fordi BlockID
er primærnøgle, og der kan kun indsættes én række.
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();
Koder
Kopiér Elevations
fra gammel Block
og tildel dem til den nye Block
.Husk kortlægningen mellem gamle IDs
og nygenererede IDs
i @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)
;
Etager
Kopiér Floors
ved hjælp af kortlægning mellem gammelt og nyt ElevationID
.Husk kortlægningen mellem gamle IDs
og nygenererede IDs
i @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)
;
Paneler
Kopiér Panels
ved hjælp af kortlægning mellem gammelt og nyt FloorID
.Dette er det sidste niveau af detaljer, så vi kan bruge simple INSERT
og husk ikke kortlægningen af 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
;