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.
- 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
UPDATEsó. - O que quer dizer "0 linhas afetadas", e por que isso não é um erro.
- A armadilha do
ANDno lugar da vírgula, que estraga dados sem dar erro. - Os erros reais: coluna que não existe,
NOT NULL,UNIQUE,FOREIGN KEY.
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ário | No SQL |
|---|---|
| Abrir o fichário certo | UPDATE clientes |
| Apagar um campo e escrever o valor novo | SET email = 'luis.brito@exemplo.com.br' |
| Achar a ficha (ou as fichas) que vão mudar | WHERE 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 temFROMnemINTO: 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
WHEREdoSELECT(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;
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.
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ê quer | Escreva |
|---|---|
| Mudar uma linha | UPDATE t SET col = valor WHERE id = 7; (pela chave primária) |
| Mudar várias colunas | SET a = 1, b = 2 (vírgula) |
| Calcular a partir do valor atual | SET estoque = estoque - 2 |
| Mudar um grupo de linhas | WHERE categoria_id = 1, WHERE id IN (86, 87), WHERE cidade = 'Recife' |
| Apagar o valor de uma coluna | SET email = NULL |
| Apagar a linha inteira | Outro comando: DELETE |
| Conferir antes | SELECT … WHERE com o mesmo WHERE |
| Ver o resultado na hora | … RETURNING colunas; |
| Poder desfazer | Uma transação (BEGIN … ROLLBACK): aula Transações |
Quando dá errado
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.
= 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).
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.
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.
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.
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.)
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 doDELETE 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?
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.
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
| Escrita | O 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 - 2 | Valor novo calculado a partir do atual |
SET preco = ROUND(preco * 1.10, 2) | Reajuste de 10%, com duas casas |
SET email = NULL | Deixa 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 sintoma | Quer dizer |
|---|---|
Coluna virou 0, sem erro | AND no lugar da vírgula no SET |
| "0 linhas afetadas" | WHERE não achou nada (id errado, = NULL…) |
no such column: telefone | A coluna não existe nessa tabela |
NOT NULL constraint failed: clientes.nome | Tentou deixar em branco um campo obrigatório |
UNIQUE constraint failed: clientes.id | O valor novo já existe numa coluna única |
FOREIGN KEY constraint failed | Aponta para uma linha que não existe |
near "cidade": syntax error | Faltou o SET |
Exercícios
1. Complete o comando
2. Duas colunas
Complete o caractere que separa as duas atribuições:
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.ANDno 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
WHEREdecide 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 = NULLapaga o valor; noWHERE, useIS NULL. Apagar a linha é comDELETE.- No editor, cada Rodar volta ao banco limpo; no terminal, o
UPDATEé gravado no arquivo.