Using merge..output to get mapping between source.id and target.id

后端 未结 2 658
隐瞒了意图╮
隐瞒了意图╮ 2020-11-22 00:13

Very simplified, I have two tables Source and Target.

declare @Source table (SourceID int identity(1,2), SourceName varchar(50))
declare @Target table (Targe         


        
2条回答
  •  旧巷少年郎
    2020-11-22 00:50

    In my opinion this is a great use of MERGE and output. I've used in several scenarios and haven't experienced any oddities to date. For example, here is test setup that clones a Folder and all Files (identity) within it into a newly created Folder (guid).

    DECLARE @FolderIndex TABLE (FolderId UNIQUEIDENTIFIER PRIMARY KEY, FolderName varchar(25));
    INSERT INTO @FolderIndex 
        (FolderId, FolderName)
        VALUES(newid(), 'OriginalFolder');
    
    DECLARE @FileIndex TABLE (FileId int identity(1,1) PRIMARY KEY, FileName varchar(10));
    INSERT INTO @FileIndex 
        (FileName)
        VALUES('test.txt');
    
    DECLARE @FileFolder TABLE (FolderId UNIQUEIDENTIFIER, FileId int, PRIMARY KEY(FolderId, FileId));
    INSERT INTO @FileFolder 
        (FolderId, FileId)
        SELECT  FolderId, 
                FileId
        FROM    @FolderIndex
        CROSS JOIN  @FileIndex;  -- just to illustrate
    
    DECLARE @sFolder TABLE (FromFolderId UNIQUEIDENTIFIER, ToFolderId UNIQUEIDENTIFIER);
    DECLARE @sFile TABLE (FromFileId int, ToFileId int);
    
    -- copy Folder Structure
    MERGE @FolderIndex fi
    USING   (   SELECT  1 [Dummy],
                        FolderId, 
                        FolderName
                FROM    @FolderIndex [fi]
                WHERE   FolderName = 'OriginalFolder'
            ) d ON  d.Dummy = 0
    WHEN NOT MATCHED 
    THEN INSERT 
        (FolderId, FolderName)
        VALUES (newid(), 'copy_'+FolderName)
    OUTPUT  d.FolderId,
            INSERTED.FolderId
    INTO    @sFolder (FromFolderId, toFolderId);
    
    -- copy File structure
    MERGE   @FileIndex fi
    USING   (   SELECT  1 [Dummy],
                        fi.FileId, 
                        fi.[FileName]
                FROM    @FileIndex fi
                INNER
                JOIN    @FileFolder fm ON 
                        fi.FileId = fm.FileId
                INNER
                JOIN    @FolderIndex fo ON 
                        fm.FolderId = fo.FolderId
                WHERE   fo.FolderName = 'OriginalFolder'
            ) d ON  d.Dummy = 0
    WHEN NOT MATCHED 
    THEN INSERT ([FileName])
        VALUES ([FileName])
    OUTPUT  d.FileId,
            INSERTED.FileId
    INTO    @sFile (FromFileId, toFileId);
    
    -- link new files to Folders
    INSERT INTO @FileFolder (FileId, FolderId)
        SELECT  sfi.toFileId, sfo.toFolderId
        FROM    @FileFolder fm
        INNER
        JOIN    @sFile sfi ON  
                fm.FileId = sfi.FromFileId
        INNER
        JOIN    @sFolder sfo ON 
                fm.FolderId = sfo.FromFolderId
    -- return    
    SELECT  * 
    FROM    @FileIndex fi 
    JOIN    @FileFolder ff ON  
            fi.FileId = ff.FileId 
    JOIN    @FolderIndex fo ON  
            ff.FolderId = fo.FolderId
    

提交回复
热议问题