Saya berasumsi bahwa Blocks.BlockID
, Elevations.ElevationID
, Floors.FloorID
, Panels.PanelID
adalah kunci utama dan IDENTITY
yang dibuat secara otomatis .
- Satu
Block
memiliki banyakElevations
. - Satu
Elevation
memiliki banyakFloors
. - Satu
Floors
memiliki 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
;