SQL UPDATE

O Luís Otávio, aquele cliente sem email, finalmente passou o endereço. A Ana não quer cadastrá-lo de novo: quer mudar a ficha que já existe. Para isso o SQL tem o UPDATE ("atualizar"). Com ele você troca o valor de uma ou mais colunas, em uma ou em muitas linhas de uma vez: corrigir um email, reajustar os preços de uma categoria, baixar o estoque depois de uma venda, marcar um pedido como entregue. E aqui aparece, pela primeira vez, a regra mais importante de todo o SQL que muda dados: o WHERE decide quais linhas mudam.

Você vai aprender
  • A forma UPDATE tabela SET coluna = valor WHERE condição; e o que cada parte faz.
  • Como mudar várias colunas de uma vez, separadas por vírgula.
  • Como calcular o valor novo a partir do valor antigo (preco = preco * 1.10, estoque = estoque - 2).
  • Como mudar muitas linhas com um UPDATE só.
  • O que quer dizer "0 linhas afetadas", e por que isso não é um erro.
  • A armadilha do AND no lugar da vírgula, que estraga dados sem dar erro.
  • Os erros reais: coluna que não existe, NOT NULL, UNIQUE, FOREIGN KEY.
Pode mudar sem medo

No editor do guia, cada Rodar começa do banco limpo: a Loja Aurora é carregada de novo e só então o seu SQL roda. Por isso os exemplos têm um SELECT depois do UPDATE, na mesma caixa: é assim que você vê a mudança. No terminal é diferente, e a seção 8 mostra.


A ideia: corrigir a ficha com borracha

No fichário de papel, atualizar um cadastro é: achar a ficha certa, apagar o campo com a borracha e escrever o valor novo. O UPDATE tem exatamente essas três partes:

No fichárioNo SQL
Abrir o fichário certoUPDATE clientes
Apagar um campo e escrever o valor novoSET email = 'luis.brito@exemplo.com.br'
Achar a ficha (ou as fichas) que vão mudarWHERE id = 7

Repare na diferença para o papel: no fichário, você mexe numa ficha por vez. No SQL, o UPDATE muda todas as linhas que passam no WHERE, sejam uma, dez ou todas. É uma ferramenta poderosa, e por isso exige atenção.


1. O primeiro UPDATE

UPDATE clientes
SET email = 'luis.brito@exemplo.com.br'
WHERE id = 7;

SELECT id, nome, email FROM clientes WHERE id = 7;
UPDATE clientes
"Atualizar clientes": a tabela que vai mudar. Repare que não tem FROM nem INTO: o nome da tabela vem direto.
SET
"Defina": daqui vem o que muda.
email = 'luis.brito@…'
A coluna, um sinal de = e o valor novo. Aqui o = não compara: ele atribui, quer dizer "passa a valer". O valor antigo (NULL, no caso) é apagado.
WHERE id = 7
Quais linhas mudam: só a do cliente 7. É o mesmo WHERE do SELECT (aula WHERE), com todas as condições que você já conhece.
;
Fim do comando. Depois vem o SELECT, só para conferir.

O quadro mostra "1 linha afetada" e, embaixo, a ficha do Luís Otávio com o email novo. Para escolher a linha, use de preferência a chave primária (o id): ela é única, então você tem certeza de que vai mudar uma linha só. Um WHERE nome = 'Luís Otávio Brito' também funcionaria hoje, mas e se amanhã houver dois clientes com esse nome?

Experimente: o cliente 15, Roberto Falcão, também deu o email: roberto.falcao@exemplo.com.br. Escreva o UPDATE antes do SELECT e rode.

SELECT id, nome, email FROM clientes WHERE id = 15;
UPDATE clientes
SET email = 'roberto.falcao@exemplo.com.br'
WHERE id = 15;

SELECT id, nome, email FROM clientes WHERE id = 15;

2. Várias colunas de uma vez

A cliente 3, Ana Beatriz Sousa, mudou-se de São Paulo para Fortaleza. Mudam a cidade e o estado. No SET, separe as colunas com vírgula:

UPDATE clientes
SET cidade = 'Fortaleza',
    estado = 'CE'
WHERE id = 3;

SELECT id, nome, cidade, estado FROM clientes WHERE id = 3;

Uma linha afetada, duas colunas mudadas. As colunas que não aparecem no SET (nome, email, nascimento, vip) ficam como estavam. Outro exemplo: o Pen Drive 32GB (produto 12) estava descontinuado, com estoque 0, e voltou a ser vendido com 50 unidades novas:

UPDATE produtos
SET estoque = 50,
    descontinuado = 0
WHERE id = 12;

SELECT id, nome, estoque, descontinuado FROM produtos WHERE id = 12;
Vírgula, não AND

Entre as colunas do SET vai vírgula. Parece natural escrever "cidade = Fortaleza e estado = CE" com AND, mas isso faz outra coisa, e sem dar erro. Veja o estrago na seção Quando dá errado.


3. O valor novo calculado a partir do antigo

Do lado direito do = pode vir uma conta, e ela pode usar o próprio valor que está na coluna. O Fone de Ouvido Bluetooth (produto 7) tinha 44 unidades, e acabaram de vender 2:

UPDATE produtos
SET estoque = estoque - 2
WHERE id = 7;

SELECT id, nome, estoque FROM produtos WHERE id = 7;

Leia estoque = estoque - 2 como "o estoque passa a ser o estoque de agora menos 2". O SQLite pega o valor atual (44), faz a conta (42) e grava o resultado. Para uma reposição, seria estoque = estoque + 50.


4. Muitas linhas com um UPDATE só

A Aurora vai reajustar em 10% todos os produtos de Papelaria (categoria 1). Não precisa de um UPDATE por produto: o WHERE escolhe os seis de uma vez.

UPDATE produtos
SET preco = preco * 1.10
WHERE categoria_id = 1;

SELECT id, nome, preco FROM produtos WHERE categoria_id = 1;

"6 linhas afetadas", e os preços aumentaram 10%. Mas olhe os valores: 13.585, 3.069, 98.989. A conta está certa, só que nenhum preço deveria ter três casas decimais. A função ROUND(valor, 2) arredonda para duas casas (ela tem aula própria: Funções Numéricas):

UPDATE produtos
SET preco = ROUND(preco * 1.10, 2)
WHERE categoria_id = 1;

SELECT id, nome, preco FROM produtos WHERE categoria_id = 1;

Agora sim: 13.59, 3.07, 98.99. Repare no Lápis: 1.15 × 1.10 = 1.265, que deveria virar 1.27, mas saiu 1.26. Não é erro do ROUND: dentro do computador, 1.265 fica guardado como 1.26499999…, um tiquinho abaixo. É a famosa "cauda" do ponto flutuante, explicada em Funções Numéricas.

Qualquer WHERE serve. Os dois clientes de Recife viram VIP:

UPDATE clientes
SET vip = 1
WHERE cidade = 'Recife';

SELECT id, nome, cidade, vip FROM clientes WHERE cidade = 'Recife';

Experimente: os pedidos 86 e 87 foram entregues no dia 2026-10-16. Escreva um único UPDATE que preenche o entregue_em dos dois (dica: WHERE id IN (86, 87), da aula IN). O SELECT lista os pedidos ainda pendentes: devem sobrar 3.

SELECT id, data, entregue_em
FROM pedidos
WHERE entregue_em IS NULL;
UPDATE pedidos
SET entregue_em = '2026-10-16'
WHERE id IN (86, 87);

SELECT id, data, entregue_em
FROM pedidos
WHERE entregue_em IS NULL;

5. Apagar um valor: SET coluna = NULL

Para deixar um campo em branco, atribua NULL (sem aspas). O cliente 6, Rafael Monteiro, avisou que o email dele foi desativado. Até ele mandar o novo, a Ana prefere apagar o antigo:

UPDATE clientes
SET email = NULL
WHERE id = 6;

SELECT id, nome, email FROM clientes WHERE id = 6;

Repare na diferença de sinal: no SET, email = NULL está certo, porque atribui. No WHERE, email = NULL está errado, porque compara, e comparar com NULL dá "não sei" (aula O Valor NULL). Para escolher as linhas em branco, o WHERE usa IS NULL.

Apagar o valor de uma coluna não é apagar a linha: o cliente 6 continua cadastrado, só sem email. Para tirar a linha inteira da tabela, o comando é outro: DELETE.


6. "0 linhas afetadas" não é erro

UPDATE clientes
SET vip = 1
WHERE id = 999;

Não existe cliente 999, e o SQLite não reclama: ele procurou as linhas que passam no WHERE, não achou nenhuma, e mudou zero. Para o banco, está tudo certo. Para você, pode ser sinal de engano: um id errado, um nome digitado diferente, ou um WHERE email = NULL. Sempre leia o número de linhas afetadas: ele diz se o UPDATE fez o que você esperava.

Ensaie com um SELECT

Antes de um UPDATE que mexe em muitas linhas, rode um SELECT com o mesmo WHERE: SELECT * FROM produtos WHERE categoria_id = 1;. As linhas que ele mostrar são exatamente as que vão mudar. Esse "ensaio" é o assunto da aula O Perigo do UPDATE e DELETE sem WHERE, que mostra o que acontece quando o WHERE é esquecido.


7. RETURNING: ver o que mudou

O SQLite aceita RETURNING no fim do UPDATE, como no INSERT: ele devolve as linhas que mudaram, já com os valores novos, sem precisar de um SELECT à parte.

UPDATE produtos
SET estoque = estoque - 2
WHERE id = 7
RETURNING id, nome, estoque;

8. No terminal, o UPDATE é para valer

No terminal, o UPDATE grava no arquivo loja.db, e não há "Rodar de novo" que traga o valor antigo de volta. Também não aparece "1 linha afetada": quando dá certo, o sqlite3 fica quieto. Para ver a contagem, ligue .changes on:

$ sqlite3 loja.db
SQLite version 3.50.4 2025-07-30 19:33:53
Enter ".help" for usage hints.
sqlite> SELECT id, nome, email FROM clientes WHERE id = 7;
7|Luís Otávio Brito|
sqlite> .changes on
sqlite> UPDATE clientes SET email = 'luis.brito@exemplo.com.br' WHERE id = 7;
changes: 1   total_changes: 1
sqlite> UPDATE clientes SET vip = 1 WHERE id = 999;
changes: 0   total_changes: 1           « nenhum cliente 999: zero mudanças, sem erro
sqlite> .changes off
sqlite> SELECT id, nome, email FROM clientes WHERE id = 7;
7|Luís Otávio Brito|luis.brito@exemplo.com.br
sqlite> UPDATE clientes SET nome = NULL WHERE id = 7;
Runtime error: NOT NULL constraint failed: clientes.nome (19)
sqlite> .quit

Os erros saem com a moldura do terminal (Runtime error: … e o código (19)), mas o miolo é o mesmo do editor. E o UPDATE que deu erro não mudou nada: o nome do Luís Otávio continua lá.


Formas diferentes de mudar dados

Você querEscreva
Mudar uma linhaUPDATE t SET col = valor WHERE id = 7; (pela chave primária)
Mudar várias colunasSET a = 1, b = 2 (vírgula)
Calcular a partir do valor atualSET estoque = estoque - 2
Mudar um grupo de linhasWHERE categoria_id = 1, WHERE id IN (86, 87), WHERE cidade = 'Recife'
Apagar o valor de uma colunaSET email = NULL
Apagar a linha inteiraOutro comando: DELETE
Conferir antesSELECT … WHERE com o mesmo WHERE
Ver o resultado na hora… RETURNING colunas;
Poder desfazerUma transação (BEGIN … ROLLBACK): aula Transações

Quando dá errado

AND no lugar da vírgula: estraga sem dar erro
UPDATE clientes
SET cidade = 'Fortaleza' AND estado = 'CE'
WHERE id = 3;

SELECT id, nome, cidade, estado FROM clientes WHERE id = 3;

O que acontece: "1 linha afetada", nenhum erro, e a cidade da Ana Beatriz virou 0, com o estado ainda SP! O SQLite leu o comando assim: "a cidade passa a valer o resultado de 'Fortaleza' AND estado = 'CE'". Isso é uma condição lógica (verdadeiro ou falso); o estado dela era 'SP', a condição deu falso, e falso no SQLite é 0. Só uma coluna mudou, e para um valor sem sentido.

Como consertar: vírgula entre as atribuições: SET cidade = 'Fortaleza', estado = 'CE'. E, de novo: confira o resultado depois de um UPDATE.

Comparou com = NULL no WHERE
UPDATE clientes
SET vip = 1
WHERE email = NULL;

O que acontece: "0 linhas afetadas". No WHERE, o = compara, e comparar com NULL nunca é verdadeiro.

Como consertar: WHERE email IS NULL (aula IS NULL e IS NOT NULL).

Coluna que não existe
UPDATE clientes
SET telefone = '(86) 99999-0000'
WHERE id = 1;

A mensagem: no such column: telefone ("não existe a coluna telefone"). Na Aurora, clientes não têm telefone; quem tem são os fornecedores. O mesmo acontece se você errar a tabela: UPDATE clientes SET preco = 1 dá no such column: preco, porque o preço é da tabela produtos.

Deixou em branco um campo obrigatório
UPDATE clientes
SET nome = NULL
WHERE id = 7;

A mensagem: NOT NULL constraint failed: clientes.nome. A coluna nome foi criada NOT NULL (aula NOT NULL), e o SQLite recusa o UPDATE inteiro.

Mudou o id para um que já existe
UPDATE clientes
SET id = 1
WHERE id = 2;

A mensagem: UNIQUE constraint failed: clientes.id. Já existe um cliente 1. Mudar a chave primária quase nunca é uma boa ideia: os pedidos apontam para ela.

Apontou para uma linha que não existe
UPDATE produtos
SET categoria_id = 99
WHERE id = 1;

A mensagem: FOREIGN KEY constraint failed. Não existe categoria 99. (No terminal, lembre: a verificação de chaves estrangeiras só vale depois de PRAGMA foreign_keys = ON;, como explica a aula INSERT INTO.)

Erros de escrita
UPDATE clientes
cidade = 'Fortaleza'
WHERE id = 3;

A mensagem: near "cidade": syntax error: faltou o SET. Outros parecidos, todos colhidos no SQLite:

  • UPDATE FROM clientes SET … (costume do DELETE FROM) → near "FROM": syntax error.
  • SET cidade = 'Fortaleza' estado = 'CE' (sem vírgula) → near "estado": syntax error.
  • SET cidade = 'Fortaleza', WHERE id = 3 (vírgula sobrando) → near "WHERE": syntax error.
  • SET cidade = "Fortaleza" (aspas duplas) → no such column: "Fortaleza" - should this be a string literal in single-quotes?
Texto numa coluna de número
UPDATE produtos
SET preco = 'barato'
WHERE id = 3;

SELECT nome, preco, typeof(preco) FROM produtos WHERE id = 3;

O que acontece: o SQLite aceitou! O preço do Lápis agora é o texto barato, e qualquer conta com ele vai dar resultado estranho. O SQLite é flexível com tipos: uma coluna REAL tenta converter o valor para número e, se não conseguir, guarda como veio. A aula Os Tipos no SQLite explica, e a CHECK mostra como proibir isso.

Como consertar: números sem aspas, com ponto: SET preco = 1.15.

Nos outros bancos

O UPDATE tabela SET coluna = valor WHERE condição é do SQL padrão e funciona igual no MySQL, no PostgreSQL e no SQL Server. O RETURNING existe também no PostgreSQL; no SQL Server, o equivalente é a cláusula OUTPUT, que pode devolver o valor de antes (DELETED.coluna) e o de depois (INSERTED.coluna). Trecho só ilustrativo, em SQL Server:

UPDATE produtos
SET estoque = estoque - 2
OUTPUT DELETED.estoque, INSERTED.estoque
WHERE id = 7;

Referência rápida

EscritaO que faz
UPDATE t SET a = 1 WHERE id = 7;Muda a coluna a da linha 7
SET a = 1, b = 'x'Muda duas colunas (vírgula entre elas)
SET estoque = estoque - 2Valor novo calculado a partir do atual
SET preco = ROUND(preco * 1.10, 2)Reajuste de 10%, com duas casas
SET email = NULLDeixa o campo em branco
WHERE …Escolhe as linhas que mudam (todas que passarem)
… RETURNING colunas;Devolve as linhas mudadas, com os valores novos
"0 linhas afetadas"Nenhuma linha passou no WHERE; não é erro
Mensagem ou sintomaQuer dizer
Coluna virou 0, sem erroAND no lugar da vírgula no SET
"0 linhas afetadas"WHERE não achou nada (id errado, = NULL…)
no such column: telefoneA coluna não existe nessa tabela
NOT NULL constraint failed: clientes.nomeTentou deixar em branco um campo obrigatório
UNIQUE constraint failed: clientes.idO valor novo já existe numa coluna única
FOREIGN KEY constraint failedAponta para uma linha que não existe
near "cidade": syntax errorFaltou o SET

Exercícios

1. Complete o comando

produtos estoque = 100 id = 9;

2. Duas colunas

Complete o caractere que separa as duas atribuições:

UPDATE clientes SET cidade = 'Recife' estado = 'PE' WHERE id = 4;

3. O Teclado Compacto (produto 9) tem 25 unidades. Depois de UPDATE produtos SET estoque = estoque + 10 WHERE id = 9;, quanto ele tem?

4. Um UPDATE respondeu "0 linhas afetadas". O que aconteceu?

5. O que UPDATE clientes SET cidade = 'Recife' AND estado = 'PE' WHERE id = 4; faz?

Missão final: reajuste dos brinquedos

Missão: todos os produtos da categoria Brinquedos (categoria_id = 5) vão ficar 5 reais mais caros. Os outros produtos não mudam. O SELECT mostra dois brinquedos e, para conferir, um livro e um artigo de esporte, que devem continuar com o preço de antes.

SELECT nome, categoria_id, preco
FROM produtos
WHERE id IN (24, 25, 29, 30);
UPDATE produtos
SET preco = preco + 5
WHERE categoria_id = 5;

SELECT nome, categoria_id, preco
FROM produtos
WHERE id IN (24, 25, 29, 30);

Se o livro e a garrafa também ficaram 5 reais mais caros, faltou o WHERE: o UPDATE mudou os 45 produtos. É exatamente o assunto da aula O Perigo do UPDATE e DELETE sem WHERE.


Resumo

  • UPDATE tabela SET coluna = valor WHERE condição; muda dados que já existem.
  • No SET, o = atribui; várias colunas vão separadas por vírgula. AND no lugar da vírgula grava 0 ou 1, sem erro.
  • O valor novo pode ser uma conta com o atual: estoque = estoque - 2, preco = ROUND(preco * 1.10, 2).
  • O WHERE decide quais linhas mudam: todas as que passarem. Para uma linha só, use a chave primária.
  • "0 linhas afetadas" não é erro: nenhuma linha passou no WHERE. Leia sempre a contagem.
  • SET coluna = NULL apaga o valor; no WHERE, use IS NULL. Apagar a linha é com DELETE.
  • No editor, cada Rodar volta ao banco limpo; no terminal, o UPDATE é gravado no arquivo.