sql >> Database teknologi >  >> RDS >> Sqlserver

Kaskadekopiér en række med alle underordnede rækker og deres underordnede rækker osv

Jeg antager, at Blocks.BlockID , Elevations.ElevationID , Floors.FloorID , Panels.PanelID er primærnøgler og autogenereret IDENTITY .

  • Én Block har mange Elevations .
  • Én Elevation har mange Floors .
  • Én Floor har mange Panels .

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
;



  1. Hives time()-funktion returnerer 12 timers urværdi

  2. Oracle-sekvenser svarende til i MySQL

  3. SQL:hvordan finder jeg ud af, om indholdet af en varchar-kolonne er numerisk?

  4. MySQL-sammenføjningstabeller grupperes efter sumproblem