Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

Salin beberapa catatan dengan hubungan master-detail

Solusi yang dijelaskan di sini akan bekerja dengan benar di lingkungan multi-pengguna.

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 .

Contoh data

INSERT INTO [dbo].[StageDetail]
    ([StageNUmber]
    ,[TypeOfStage]
    ,[Distance])
VALUES
    ('sn01','t1','D1'),
    ('sn02','t2','D2'),
    ('sn03','t3','D3');

INSERT INTO [dbo].[StageDetailItem]
    ([StageDetailID]
    ,[Road]
    ,[CostPer])
VALUES
    (1,'r1_1','C11'),
    (1,'r1_2','C12'),
    (1,'r1_3','C13'),
    (1,'r1_4','C14'),
    (1,'r1_5','C15'),

    (2,'r2_1','C16'),
    (2,'r2_2','C17'),
    (2,'r2_3','C18'),
    (2,'r2_4','C19'),
    (2,'r2_5','C20'),

    (3,'r3_1','C21'),
    (3,'r3_2','C22'),
    (3,'r3_3','C23'),
    (3,'r3_4','C24'),
    (3,'r3_5','C25');

Kueri

Deklarasikan variabel tabel (atau tabel sementara) untuk menyimpan pemetaan antara ID lama dan baru.

DECLARE @T TABLE(OldStageDetailID int, NewStageDetailID int);

Pertama buat salinan baris dari StageDetail tabel mengingat pemetaan ID dalam variabel tabel.

MERGE INTO [dbo].[StageDetail]
USING
(
    SELECT [StageDetailID],[StageNUmber],[TypeOfStage],[Distance]
    FROM [dbo].[StageDetail]
) AS Src
ON 1 = 0
WHEN NOT MATCHED BY TARGET THEN
INSERT ([StageNUmber],[TypeOfStage],[Distance])
VALUES
    (Src.[StageNUmber]
    ,Src.[TypeOfStage]
    ,Src.[Distance])
OUTPUT 
    Src.[StageDetailID] AS OldStageDetailID
    ,inserted.[StageDetailID] AS NewStageDetailID
INTO @T(OldStageDetailID, NewStageDetailID)
;

Kemudian salin baris dari StageDetailItem menggunakan StageDetailIDs baru .

INSERT INTO [dbo].[StageDetailItem]
    ([StageDetailID]
    ,[Road]
    ,[CostPer])
SELECT
    T.[NewStageDetailID]
    ,[dbo].[StageDetailItem].[Road]
    ,[dbo].[StageDetailItem].[CostPer]
FROM
    [dbo].[StageDetailItem]
    INNER JOIN @T AS T ON T.OldStageDetailID = [dbo].[StageDetailItem].StageDetailID
;

Hasil

SELECT * FROM [dbo].[StageDetail]

+---------------+-------------+-------------+----------+
| StageDetailID | StageNUmber | TypeOfStage | Distance |
+---------------+-------------+-------------+----------+
|             1 | sn01        | t1          | D1       |
|             2 | sn02        | t2          | D2       |
|             3 | sn03        | t3          | D3       |
|             4 | sn01        | t1          | D1       |
|             5 | sn02        | t2          | D2       |
|             6 | sn03        | t3          | D3       |
+---------------+-------------+-------------+----------+

.

SELECT * FROM [dbo].[StageDetailItem]

+-------------------+---------------+------+---------+
| StageDetailItemID | StageDetailID | Road | CostPer |
+-------------------+---------------+------+---------+
|                 1 |             1 | r1_1 | C11     |
|                 2 |             1 | r1_2 | C12     |
|                 3 |             1 | r1_3 | C13     |
|                 4 |             1 | r1_4 | C14     |
|                 5 |             1 | r1_5 | C15     |
|                 6 |             2 | r2_1 | C16     |
|                 7 |             2 | r2_2 | C17     |
|                 8 |             2 | r2_3 | C18     |
|                 9 |             2 | r2_4 | C19     |
|                10 |             2 | r2_5 | C20     |
|                11 |             3 | r3_1 | C21     |
|                12 |             3 | r3_2 | C22     |
|                13 |             3 | r3_3 | C23     |
|                14 |             3 | r3_4 | C24     |
|                15 |             3 | r3_5 | C25     |
|                16 |             4 | r1_1 | C11     |
|                17 |             4 | r1_2 | C12     |
|                18 |             4 | r1_3 | C13     |
|                19 |             4 | r1_4 | C14     |
|                20 |             4 | r1_5 | C15     |
|                21 |             5 | r2_1 | C16     |
|                22 |             5 | r2_2 | C17     |
|                23 |             5 | r2_3 | C18     |
|                24 |             5 | r2_4 | C19     |
|                25 |             5 | r2_5 | C20     |
|                26 |             6 | r3_1 | C21     |
|                27 |             6 | r3_2 | C22     |
|                28 |             6 | r3_3 | C23     |
|                29 |             6 | r3_4 | C24     |
|                30 |             6 | r3_5 | C25     |
+-------------------+---------------+------+---------+



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bagaimana Anda mengatur autocommit dalam sesi SQL Server?

  2. Kerangka Entitas tidak berfungsi dengan tabel temporal

  3. SQL Server Ubah Nama Basis Data

  4. Bagaimana LEFT OUTER JOIN mengembalikan lebih banyak catatan daripada yang ada di tabel kiri?

  5. Cara Membuat Kunci Asing di SQL Server (Contoh T-SQL)