SQL: Inserir se Não Existir, Atualizar se Existir

No desenvolvimento de aplicações, é comum a necessidade de inserir um registro no banco de dados se ele não existir, ou atualizá-lo caso já exista. Este artigo aborda diferentes abordagens em SQL, com foco em MySQL, para implementar essa lógica de inserção ou atualização condicional.

Abordagem 1: Usando INSERT INTO com ON DUPLICATE KEY UPDATE

No MySQL, a cláusula ON DUPLICATE KEY UPDATE permite executar uma atualização se uma chave primária ou índice único for violada durante a inserção. Por exemplo, considerando uma tabela chamada cadastro com colunas id_pessoa, nome_completo e idade:

INSERT INTO cadastro (id_pessoa, nome_completo, idade) 
VALUES (101, 'ana_costa', 30) 
ON DUPLICATE KEY UPDATE nome_completo = 'ana_costa', idade = 30;

Se id_pessoa = 101 não existir, o regsitro será inserido. Se já existir, o comando equivalerá a:

UPDATE cadastro 
SET nome_completo = 'ana_costa', idade = 30 
WHERE id_pessoa = 101;

Caso a coluna idade também seja única, a atualização ocorrerá se qualquer uma das chaves for duplicada. É recomendável evitar o uso dessa cláusula em tabelas com múltiplos índices únicos. Além disso, é possível combinar com subconsultas para atualizações em lote:

INSERT INTO cadastro (id_pessoa, nome_completo)
    SELECT id_pessoa + 100, 'nome_temporario' FROM cadastro WHERE id_pessoa >= 50
ON DUPLICATE KEY UPDATE nome_completo = VALUES(nome_completo);

Abordagem 2: Utilizando Procedimentos Armazenados

Outra forma é criar um procedimento armazenado que verifica a existência antes de decidir entre inserção ou atualização:

DELIMITER //
CREATE PROCEDURE atualizar_ou_inserir(IN p_id INT, IN p_nome VARCHAR(50), IN p_idade INT)
BEGIN
    IF EXISTS (SELECT 1 FROM cadastro WHERE id_pessoa = p_id) THEN
        UPDATE cadastro SET nome_completo = p_nome, idade = p_idade WHERE id_pessoa = p_id;
    ELSE
        INSERT INTO cadastro (id_pessoa, nome_completo, idade) VALUES (p_id, p_nome, p_idade);
    END IF;
END //
DELIMITER ;

Abordagem 3: Aplicando WHERE NOT EXISTS

A cláusula WHERE NOT EXISTS permite condicionar a inserção com base na ausência de registros específicos. Exemplo:

INSERT INTO cadastro (id_pessoa, nome_completo)
SELECT id_pessoa + 200, 'novo_usuario' 
FROM cadastro 
WHERE NOT EXISTS (
    SELECT * FROM cadastro WHERE id_pessoa = 300
) 
AND id_pessoa = 50;

Se a subconsulta não retornar resultados, a inserção ocorrerá com os dados fornecidos. Essa técnica é útil para inserções condicionais baseadas em critérios complexos.

Abordagem 4: Usando REPLACE INTO

O comando REPLACE INTO funciona de forma semelhante ao INSERT INTO, mas remove registros existentes que conflitam com chaves primárias ou índices únicos antes de inserir o novo regsitro. Exemplo:

REPLACE INTO cadastro (id_pessoa, nome_completo, idade) 
VALUES (101, 'ana_costa_atualizada', 31);

Isso deletará o registro com id_pessoa = 101 se existir e inserirá o novo. Note que essa abordagem requer permissões de exclusão e pode afetar chaves auto-incremento. Portanto, deve ser usada com cautela, especialmente em tabelas com relacionamentos.

Ao escolher entre essas abordagens, considere fatores como desempenho, integridade dos dados e requisitos específicos do projeto.

Tags: MySQL SQL INSERT ON DUPLICATE KEY REPLACE INTO procedimentos armazenados

Publicado em 5-29 21:03 por Thomas