(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa

Como fazer MERGE (upsert) numa tabela Delta no Lakehouse

João Barros 07 de July de 2026 4 min de leitura

O upsert é a operação que, de uma só vez, atualiza as linhas que já existem e insere as que são novas. Numa tabela Delta do Lakehouse, o comando MERGE faz exatamente isto de forma atómica: evita duplicados e mantém a tabela consistente mesmo quando os dados de origem chegam em lotes. É por isso a base de qualquer carregamento incremental fiável, muito usado para atualizar dimensões e aplicar alterações vindas de um sistema de origem.

Pré-requisitos

  • Um workspace com capacidade Microsoft Fabric e um Lakehouse criado.
  • Um notebook do Fabric ligado a esse Lakehouse.
  • Uma tabela Delta de destino (por exemplo, dim_clientes) ou vontade de criar uma.
  • Conhecimentos básicos de SQL ou PySpark.

Passo 1: Preparar a tabela de destino

O upsert precisa de uma tabela Delta de destino. Se ainda não a tens, cria uma pequena tabela de exemplo. No Lakehouse as tabelas são Delta por omissão, mas podes indicá-lo de forma explícita com USING DELTA. O IF NOT EXISTS torna o passo seguro de repetir, sem apagar dados já existentes.

CREATE TABLE IF NOT EXISTS dim_clientes (
  cliente_id INT,
  nome STRING,
  cidade STRING
) USING DELTA;

Passo 2: Criar a origem com os novos dados

A origem é o lote com as linhas novas e as alteradas. Para o exemplo, cria um DataFrame e regista-o como vista temporária, para o poderes referir no SQL. Repara que os clientes 1 e 2 vão servir para atualizar e o 3 é novo, para inserir.

from pyspark.sql import Row

origem = spark.createDataFrame([
    Row(cliente_id=1, nome="Ana Silva",   cidade="Porto"),
    Row(cliente_id=2, nome="Bruno Costa", cidade="Lisboa"),
    Row(cliente_id=3, nome="Carla Dias",  cidade="Braga"),
])
origem.createOrReplaceTempView("origem_clientes")

Passo 3: Escrever o MERGE em SQL

O MERGE compara o destino com a origem através de uma chave. Quando há correspondência (WHEN MATCHED) atualiza a linha; quando não há (WHEN NOT MATCHED) insere uma nova. Tudo acontece numa única transação, por isso quem estiver a ler a tabela nunca vê um estado a meio. Esta é a forma mais legível de escrever um upsert.

MERGE INTO dim_clientes AS destino
USING origem_clientes AS origem
  ON destino.cliente_id = origem.cliente_id
WHEN MATCHED THEN
  UPDATE SET destino.nome   = origem.nome,
             destino.cidade = origem.cidade
WHEN NOT MATCHED THEN
  INSERT (cliente_id, nome, cidade)
  VALUES (origem.cliente_id, origem.nome, origem.cidade);
Dica: a chave usada no ON deve ser única na origem. Se existirem ids repetidos, o MERGE devolve o erro "multiple source rows matched". Remove os duplicados antes de correr o comando.

Passo 4: A alternativa em PySpark (DeltaTable)

Se preferes Python, a API DeltaTable faz o mesmo upsert sem escreveres SQL. Os métodos whenMatchedUpdateAll e whenNotMatchedInsertAll são atalhos úteis quando as colunas da origem e do destino coincidem; se precisares de controlo fino, usa whenMatchedUpdate e indica apenas as colunas a alterar.

from delta.tables import DeltaTable

destino = DeltaTable.forName(spark, "dim_clientes")

(destino.alias("destino")
    .merge(origem.alias("origem"),
           "destino.cliente_id = origem.cliente_id")
    .whenMatchedUpdateAll()
    .whenNotMatchedInsertAll()
    .execute())

Verificar o resultado

Consulta a tabela e confirma que o cliente 3 foi inserido e que os clientes 1 e 2 ficaram com os valores mais recentes, sem linhas duplicadas. Se contares as linhas, deves ter exatamente três.

SELECT cliente_id, nome, cidade
FROM dim_clientes
ORDER BY cliente_id;

Para confirmar que o MERGE foi registado como uma nova versão da tabela Delta, corre DESCRIBE HISTORY dim_clientes e procura a operação MERGE na coluna operation.

Conclusão

Com o comando MERGE passas a fazer upserts fiáveis numa tabela Delta do Lakehouse, a base de qualquer carregamento incremental. A seguir, experimenta acrescentar uma condição como WHEN MATCHED AND destino.cidade <> origem.cidade para só atualizar quando algo muda de facto, ou usar uma coluna de data para processar apenas os registos mais recentes. Qual vai ser a primeira tabela do teu Lakehouse a migrar para um upsert com MERGE?