sql >> データベース >  >> RDS >> Sqlserver

マスターと詳細の関係を持つ複数のレコードをコピーする

    ここで説明するソリューションは、マルチユーザー環境で正しく機能します。

    MERGEを使用します OUTPUTを使用 条項。

    MERGE INSERTできます 、UPDATE およびDELETE 行。この場合、必要なのはINSERTだけです。 。

    1=0 は常にfalseであるため、NOT MATCHED BY TARGET 一部は常に実行されます。通常、他のブランチが存在する可能性があります。ドキュメントを参照してください。WHEN MATCHED 通常、UPDATEに使用されます;WHEN NOT MATCHED BY SOURCE 通常、DELETEに使用されます 、ただし、ここでは必要ありません。

    この複雑な形式のMERGE 単純なINSERTと同等です 、ただし、単純なINSERTとは異なります そのOUTPUT 句を使用すると、必要な列を参照できます。ソーステーブルと宛先テーブルの両方から列を取得できるため、古い既存のIDとIDENTITYによって生成された新しいIDの間のマッピングを保存できます。 。

    サンプルデータ

    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');
    

    クエリ

    古いIDと新しいIDの間のマッピングを保持するために、テーブル変数(または一時テーブル)を宣言します。

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

    まず、StageDetailから行のコピーを作成します テーブル変数内のIDのマッピングを記憶しているテーブル。

    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)
    ;
    

    次に、StageDetailItemから行をコピーします 新しいStageDetailIDsを使用する 。

    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
    ;
    

    結果

    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. Oracleデータベースの例でのJava

    2. Mysqlエラー1005(HY000):テーブル'tmp'を作成できません(errno:13)

    3. データベースに時間(hh:mm)を保存するための最良の方法

    4. MySQL:=true対BOOLEANではtrue。いつ使用することをお勧めしますか?そして、どちらがベンダーに依存していませんか?