quinta-feira, 28 de outubro de 2010

SQL MERGE no MySQL

Hoje finalmente me deparei com uma feature cuja solução direta era fazer um MERGE no MySQL.

Para minha surpresa o MySQL não suporte MERGE [1].

Como assim ? Este comando existe desde 2008 no padrão SQL:2008 e ainda não foi implementado.
Enfim, é o custo de não pagar por uma licença.

Pesquisando um pouco descobri outro comando para fazer o trabalho do MERGE.
O ponto negativo é que terei que usar um comando específico do MySQL.

Depois se quiser trocar de banco de dados terei que reescrever todas as queries.
Foda né ? Posteriormente qual o custo disso ?
Não compensa pagar logo a licença de um BD decente ?
Pode ser que o custo de adaptação posterior em termos de desenvolvimento, testes, homologação seja muito mais caro que pagar a licença do Oracle ou DB2.

Enfim, uma coisa para se pensar...

Mas voltando a solução do problema.
A primeira solução com que me deparei foi o REPLACE [3].
Mas lendo a documentação me deparei com a seguinte frase.

REPLACE works exactly like INSERT, except that if an old row in the table has the same value as a new row for aPRIMARY KEY or a UNIQUE index, the old row is deleted before the new row is inserted.

Porque diabos ele faz um DELETE e depois um INSERT ao invés de fazer um simples UPDATE ?
Alguém pode me explicar isso ?

Isso inviabilizou o uso do REPLACE devido a restrições de chaves estrangeiras que todos conhecem. Não poderia apagar e escrever linhas referenciadas por outras tabelas.

Pesquisando com mais cuidado achei o salvado da pátria que é o

INSERT ... ON DUPLICATE KEY UPDATE [4]

Pois bem, ele resolve exatamente o que queria fazer com o MERGE.
O único problema é que isso é uma extensão do MySQL deixando a query fora do padrão.

Para referência segue um query com o KEY UPDATE

INSERT INTO USERS ( id, name, location)
VALUES
( 1, 'leonardo', 'mantena')
ON DUPLICATE KEY UPDATE
name = VALUES (name),
location = VALUES (location)


6 comentários:

Luiz Paulo disse...

Muito simples essa solução. Muito mais simples que o merge inclusive.

Bom post Leo.
[]'s

Walter Cruz disse...

Achei um pouco alarmista... aliás.. a maioria dos bancos não implementa o SQL 2008 totalmente, exceto talvez pelo próprio DB2, já que a especificação é praticamente baseada nele.

leoxtc disse...

Maioria dos bancos open-source.

DB2 e Oracle que são os dois principais bancos comerciais implementam o MERGE.

Anônimo disse...

A partir dessas peculiaridades (idiossincrasias de implementação) aí fica claro que o código SQL feito para um banco não irá funcionar facilmente em outro, ou seja, a ideia de que o desenvolvimento em camadas garante trocar de banco de dados facilmente é apenas uma falácia. Eu sou a favor do desenvolvimento em camadas sim, mas a decisão do banco de dados a ser utilizado no sistema não é algo fácil de ser trocado no futuro. O mesmo vale para a camada de apresentação (interface com o usuário). Também vale para ilustrar outro cenário. Dizem que software open source é tão bom quanto o proprietário, mas tá aí um exemplo claro que na prática a história é outra. Bom post!

Jan Palach disse...

"Dizem que software open source é tão bom quanto o proprietário, mas tá aí um exemplo claro que na prática a história é outra. Bom post!"

Depende de quem desenvolve não? Não se é pago ou free....

Unknown disse...

Não entendo com faria isso com o merge. O merge atualiza a coluna quando já existe o registro, certo?