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!

E agora DBA?

No inicio de 2009 meu diretor entrou na sala de reuniões e ordenou "Precisamos de um DBA!"

Depois disso meus dias profisionais nunca mais foram os mesmos.

Até então eu era um programador VB6 ja experimentado e um pouco iniciante em .Net, mas alguma coisa me impulsionou a entrar na sala do gerente e perguntar : "Será que eu posso ser o DBA?"
Então depois de aproximadamente 9 anos de experiencia como programador eis que volto a condição de Junior!
Algum tempo ja passou desde que isso aconteceu e ja consegui aprender alguma coisa, só que eu quero bem mais.
Se um dia eu chegar perto do que esse cara aqui eu ja vou ficar bem feliz.

Mas chega de lero lero. Tenho dois objetivos com esse blog.

O primeiro é publicar informações sobre o SQL Server 2008 que ficam escondidas nos recantos dos manuais e da web e que muitos DBAs brasileiros perdem por não termos uma tradução ou mesmo o tempo para ir atrás das perolas.
O segundo é mais complicado. Atualmente ando um pouco chateado com treinamentos oficiais da Microsoft, acho que custam caro demais, desprezam os alunos e muitas vezes o conteudo é pura leitura de apostila. E como eu ando um pouco sem grana, resolvi conseguir uma certificação sem fazer curso nenhum. Só por mim mesmo.

Bem, espero que esse espaço seja util para alguem. (pelo menos para mim) e que passe desse primeiro post. (ja tive muitos blogs de um post só)

Um abraço comunidade!