Poupe tempo com MERGE

Atualmente trabalho em uma empresa de GED onde cada documento é identificado com uma porção de campos que chamamos de indexadores. É pratica comum a nossos clientes reduzirem o custo de digitação enviando uma base de dados com todos os indexadores. Infelizmente, também é pratica comum que a base venha repetida ou então ela seja uma mescla de dados já carregados anteriormente, registros novos e até atualizações da informação.
Tudo isso é chato de carregar. Ou melhor, era!! Quem tem o prazer de lidar com o SQL 2008 já pode utilizar o MERGE.
Se você perguntar ao Google o que significa MERGE em português, nosso pastor te responderá:
verbo fundir,amalgamar,misturar,diluir,desaparecer,imergir

Portanto, a idéia do MERGE é juntar duas tabelas e realizar operações de INSERT,UPDATE e DELETE para obter um resultado final .

Para dar um exemplo pratico , vamos iniciar criando duas tabelas, a TabelaAlvo (no caso cima é minha tabela com os dados dos documentos) e a TabelaFonte (a base que o cliente mandou com atualizações)

CREATE TABLE TabelaAlvo
(
ChavePrimaria int NOT NULL PRIMARY KEY,
CampoTexto varchar(50) NULL
)
CREATE TABLE TabelaFonte
(
ChavePrimaria int NOT NULL PRIMARY KEY,
CampoTexto varchar(50) NULL
)
GO

INSERT INTO TabelaFonte VALUES (1,'Texto 1')
INSERT INTO TabelaFonte VALUES (2,'Texto 2')
INSERT INTO TabelaFonte VALUES (3,'Texto 3')
INSERT INTO TabelaFonte VALUES (4,'Texto 4')
INSERT INTO TabelaFonte VALUES (5,'Texto 5')

INSERT INTO TabelaAlvo VALUES (4,NULL)
INSERT INTO TabelaAlvo VALUES (5,NULL)
INSERT INTO TabelaAlvo VALUES (6,'Texto 6')
INSERT INTO TabelaAlvo VALUES (7,'Texto 7')


Portanto temos 5 registros na TabelaFonte sendo que dois deles já existem na tabela TabelaAlvo ( note que o campo CampoTexto está nulo, simulando um dado desatualizado)
Para regularizarmos a situação teríamos que executar duas operações.

Primeiro um INSERT com SELECT para incluirmos só o que é novo

INSERT INTO TabelaAlvo (ChavePrimaria,CampoTexto)
SELECT
F.ChavePrimaria,F.CampoTexto
FROM
TabelaFonte F
LEFT JOIN TabelaAlvo A ON F.ChavePrimaria = A.ChavePrimaria
WHERE
D.ChavePrimaria IS NULL
Depois UPDATE para atualizarmos o que já existe.
UPDATE A
SET A.CampoTexto = F.CampoTexto
FROM
TabelaAlvo A
INNER JOIN TabelaFonte F ON A.ChavePrimaria = F.ChavePrimaria


Agora veja a syntaxe do Merge para a mesma operação

MERGE TabelaAlvo A
USING TabelaFonte F
ON A.ChavePrimaria = F.ChavePrimaria
WHEN MATCHED
THEN UPDATE SET A.CampoTexto = F.CampoTexto
WHEN NOT MATCHED
THEN INSERT (ChavePrimaria,CampoTexto) VALUES (ChavePrimaria,CampoTexto);



Vamos a Syntaxe.

Após o Merge coloque a tabela alvo, aquela que você vai realizar as operações de insert/update/
O USING é a tabela origem, onde você buscara as informações
Após o ON coloque a condição de igualdade das duas tabelas
WHEN MATCHED é a clausula executada onde a condição for satisfeita. (o INNER JOIN do UPDATE)
WHEN NOT MATCHED é o que será executado quando existirem dados na fonte que não existem no alvo. (o INSERT..SELECT)
Existe também uma terceira opção a WHEN NOT MATCHED BY SOURCE que realiza uma operação na tabela alvo para registros que existam nela e não existam na origem.
Exemplo: Quero deixar as duas tabelas exatamente iguais.

MERGE TabelaAlvo A
USING TabelaFonte F
ON A.ChavePrimaria = F.ChavePrimaria
WHEN MATCHED
THEN UPDATE SET A.CampoTexto = F.CampoTexto
WHEN NOT MATCHED
THEN INSERT (ChavePrimaria,CampoTexto) VALUES (ChavePrimaria,CampoTexto)
WHEN NOT MATCHED BY SOURCE
THEN DELETE;


Isso é o basico depois disso existem n alternativas dentro do MERGE, sugiro uma leitura no BOL http://technet.microsoft.com/en-us/library/bb510625.aspx


Agradeço a você pela sua atenção e espero que isso ajude em algo!