MERGE Statement

O MERGE, permite combinar operações de inserção, atualização e eliminação numa única instrução, otimizando assim as transações e a manutenção de dados.

É uma instrução poderosa que permite realizar operações de inserção, atualização ou exclusão numa única declaração.

Esta instrução é particularmente útil quando se deseja sincronizar duas tabelas, ou seja, atualizar uma tabela de destino com base nos dados de uma tabela de origem.

Sintaxe básica

MERGE TOP (value) <tabela_destino> 
USING <tabela_fonte>   
ON <merge_condições_de_pesquisa>  
    [ QUANDO COINCIDE [ AND <condição_de_pesquisa_de_cláusula> ]  
        THEN <merge_correspondida> ] 
    [ QUANDO NÃO COINCIDE [ BY TARGET ] [ AND <condição_de_pesquisa_de_cláusula> ]  
        THEN <merge_não_correspondido> ]  
    [ QUANDO NÃO COINCIDE PELA FONTE [ AND <condição_de_pesquisa_de_cláusula> ]  
        THEN <merge_coincide> ] 
    [ <cláusula_de_saída> ]  
    [ OPÇÃO ( <query_hint> ) ]      

A sintaxe básica do MERGE começa com a palavra-chave MERGE seguida pelo nome da tabela de destino. Depois, utiliza-se a cláusula USING para especificar a tabela de origem dos dados.

A cláusula ON define a condição de correspondência entre as tabelas de origem e destino. As cláusulas WHEN MATCHED e WHEN NOT MATCHED especificam as ações a serem tomadas quando os dados correspondem ou não.

Por exemplo, pode-se atualizar os dados na tabela de destino se eles correspondem aos da tabela de origem, ou inserir novos dados se não houver correspondência. É importante frisar que o MERGE deve ser usado com cuidado, pois a execução de múltiplas operações numa única instrução pode ser complexa e suscetível a erros se não for bem compreendida e cuidadosamente implementada.

Tem que garantir que as condições de correspondência sejam corretas para evitar resultados inesperados.

Em resumo, o MERGE é uma ferramenta versátil em T-SQL que, quando usada corretamente, pode simplificar e otimizar as operações de sincronização de dados entre tabelas.

Exemplo 1


USE AdventureWorks
GO

--Criar uma tabela de destino

CREATE TABLE dbo.Students (
    StudentId int IDENTITY(1,1) NOT NULL,
    FirstName varchar(50),
    LastName varchar(50)
);
GO

INSERT INTO dbo.Students VALUES 
    ('Pedro', 'Gato'), 
    ('Julia', 'Caracol'), 
    ('Margarida', 'Borboleta');
GO

SELECT * FROM Students;
GO

--MERGE statement

DECLARE @Changes TABLE(Change VARCHAR(20));

MERGE INTO dbo.Students AS Target  
USING ( VALUES 
            (3, 'Clara', 'Lémure'), 
            (7, 'Carlos','Águia'), 
            (8, 'Silvia', 'Arara')
        ) AS Source ( StudentId, FirstName, LastName )  
ON Target.StudentId = Source.StudentId
AND Target.FirstName = Source.FirstName
WHEN MATCHED THEN
    UPDATE SET FirstName = Source.FirstName, LastName = Source.LastName
WHEN NOT MATCHED BY TARGET THEN
    INSERT (FirstName, LastName) VALUES (Source.FirstName, Source.LastName)
OUTPUT $action INTO @Changes;

SELECT Change, COUNT(*) AS Count  
FROM @Changes  
GROUP BY Change;

SELECT * FROM dbo.Students;

Desafio: O estudante com o ID 3 é Margarida ou a Clara?

Exemplo 2


--Criar tabela de origem
CREATE TABLE dbo.Courses (
    StudentId int IDENTITY(1,1) NOT NULL,
    FirstName varchar(50),
    LastName varchar(50),
    Course varchar(50)
);
GO

INSERT INTO dbo.Courses VALUES 
    ('Pedro', 'Gato','SQL'), 
    ('Julia', 'Caracol','SQL'), 
    ('Catarina', 'Tubarão','SQL');
GO


SELECT * FROM dbo.Courses;
GO

--MERGE statement

SET IDENTITY_INSERT dbo.Students ON;
GO

MERGE dbo.Students AS TARGET
USING dbo.Courses AS SOURCE 
ON (TARGET.StudentId = SOURCE.StudentId) 
WHEN MATCHED AND TARGET.FirstName <> SOURCE.FirstName AND TARGET.LastName  <> SOURCE.LastName  
THEN UPDATE SET TARGET.FirstName = SOURCE.FirstName, TARGET.LastName  = SOURCE.LastName  
WHEN NOT MATCHED BY TARGET 
THEN INSERT (StudentId, FirstName, LastName ) VALUES (SOURCE.StudentId, SOURCE.FirstName, SOURCE.LastName )
WHEN NOT MATCHED BY SOURCE 
THEN DELETE 
OUTPUT $action, 
DELETED.StudentId AS TargetStudentId, 
DELETED.FirstName AS TargetFirstName, 
DELETED.LastName  AS TargetLastName , 
INSERTED.StudentId AS SourceStudentId, 
INSERTED.FirstName AS SourceFirstName, 
INSERTED.LastName  AS SourceLastName; 

SELECT @@ROWCOUNT;
GO



SELECT * FROM dbo.students;
GO

Tabela de destino apos finalizar o exemplo 1.

StudentId FirstName LastName
1 Pedro Gato
2 Julia Caracol
3 Margarida Borboleta
4 Clara Lémure
5 Carlos Águia
6 Silvia Arara

Tabela de destino do exemplo 2 depois do merge.

StudentId FirstName LastName
1 Pedro Gato
2 Julia Caracol
3 Catarina Tubarão




Documentação oficial da Microsoft