Saya berasumsi bahwa Blocks.BlockID , Elevations.ElevationID , Floors.FloorID , Panels.PanelID adalah kunci utama dan IDENTITY yang dibuat secara otomatis .
- Satu
Blockmemiliki banyakElevations. - Satu
Elevationmemiliki banyakFloors. - Satu
Floorsmemiliki banyakPanels.
Saya akan menggunakan MERGE
dengan OUTPUT klausa.
MERGE dapat INSERT , UPDATE dan DELETE baris. Dalam hal ini kita hanya perlu INSERT .
1=0 selalu salah, jadi NOT MATCHED BY TARGET bagian selalu dieksekusi. Secara umum, mungkin ada cabang lain, lihat dokumen.WHEN MATCHED biasanya digunakan untuk UPDATE;WHEN NOT MATCHED BY SOURCE biasanya digunakan untuk DELETE , tapi kita tidak membutuhkannya di sini.
Bentuk rumit dari MERGE setara dengan INSERT sederhana , tetapi tidak seperti INSERT sederhana OUTPUT-nya klausa memungkinkan untuk merujuk ke kolom yang kita butuhkan. Ini memungkinkan untuk mengambil kolom dari tabel sumber dan tujuan sehingga menyimpan pemetaan antara ID lama yang ada dan ID baru yang dihasilkan oleh IDENTITY .
Blokir
Salin yang diberikan Block dan ingat IDs dari Block new yang baru .Kita dapat menggunakan INSERT sederhana dan SCOPE_IDENTITY di sini, karena BlockID adalah kunci utama dan hanya satu baris yang dapat dimasukkan.
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();
Elevasi
Salin Elevation dari Block lama dan tetapkan mereka ke Block baru .Ingat pemetaan antara IDs lama dan IDs yang baru dibuat di @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)
;
Lantai
Salin Floors menggunakan pemetaan antara ElevationID lama dan baru .Ingat pemetaan antara IDs lama dan IDs yang baru dibuat di @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)
;
Panel
Salin Panels menggunakan pemetaan antara FloorID lama dan baru .Ini adalah detail tingkat terakhir, jadi kita bisa menggunakan INSERT sederhana dan jangan ingat pemetaan 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
;