Deletando Dados
DELETE -- removendo registros
O DELETE remove registros do banco de dados. A sintaxe e simples, mas o perigo tambem:
DELETE FROM tabela WHERE condicao;
DELETE basico
-- Deletar um usuario especifico
DELETE FROM usuarios WHERE id = 42;
-- Deletar pedidos cancelados
DELETE FROM pedidos WHERE status = 'cancelado';
-- Deletar logs antigos
DELETE FROM logs WHERE data_criacao < '2024-01-01';
A tecnica do SELECT antes do DELETE
Sempre teste com SELECT antes de deletar. Essa tecnica salva vidas:
-- PASSO 1: Veja o que sera deletado
SELECT id, nome, email FROM usuarios
WHERE ultimo_login < '2024-01-01'
AND status = 'inativo';
-- → Confira a lista! Sao esses mesmos?
-- PASSO 2: So entao delete
DELETE FROM usuarios
WHERE ultimo_login < '2024-01-01'
AND status = 'inativo';
DELETE com condicoes complexas
Voce pode usar todos os operadores que aprendeu no WHERE:
-- Deletar produtos sem estoque de categorias especificas
DELETE FROM produtos
WHERE estoque = 0
AND categoria IN ('eletronicos', 'informatica');
-- Deletar notificacoes lidas com mais de 30 dias
DELETE FROM notificacoes
WHERE lida = true
AND data_criacao < NOW() - INTERVAL '30 days';
-- Deletar tentativas de login falhas antigas
DELETE FROM login_tentativas
WHERE sucesso = false
AND data_tentativa < NOW() - INTERVAL '7 days';
DELETE com RETURNING (PostgreSQL)
Quer saber exatamente o que foi deletado? Use RETURNING:
DELETE FROM usuarios
WHERE status = 'inativo'
AND ultimo_login < '2023-01-01'
RETURNING id, nome, email;
-- → Retorna os dados de cada registro que foi removido
Isso e otimo para logs de auditoria ou para confirmar que deletou os registros certos.
DELETE vs TRUNCATE
-- DELETE: remove linha por linha, pode usar WHERE
DELETE FROM logs WHERE data < '2024-01-01';
-- TRUNCATE: limpa a tabela INTEIRA de uma vez
-- Nao aceita WHERE, mas e MUITO mais rapido para tabelas grandes
TRUNCATE TABLE logs;
-- TRUNCATE resetando o contador de ID (auto increment)
TRUNCATE TABLE logs RESTART IDENTITY;
Soft Delete vs Hard Delete
Na pratica, muitos sistemas nao deletam de verdade. Em vez disso, marcam o registro como "deletado":
-- Hard delete: remove do banco (irreversivel)
DELETE FROM usuarios WHERE id = 42;
-- Soft delete: marca como deletado (reversivel)
UPDATE usuarios
SET deletado_em = NOW(),
status = 'deletado'
WHERE id = 42;
-- Para "restaurar", basta limpar a marca
UPDATE usuarios
SET deletado_em = NULL,
status = 'ativo'
WHERE id = 42;
-- Nas consultas, sempre filtre os deletados
SELECT * FROM usuarios WHERE deletado_em IS NULL;
No Prisma
// Deletar um registro (exige campo unico no where)
const deletado = await prisma.usuario.delete({
where: { id: 42 }
})
// → retorna o registro que foi deletado
// Deletar varios registros
const resultado = await prisma.pedido.deleteMany({
where: { status: 'cancelado' }
})
// → resultado.count = numero de registros deletados
// Deletar todos os registros de uma tabela
const todos = await prisma.log.deleteMany()
// → cuidado! Equivale a DELETE sem WHERE
// Soft delete com Prisma
const softDelete = await prisma.usuario.update({
where: { id: 42 },
data: { deletadoEm: new Date() }
})
No Drizzle
import { eq, lt, and } from 'drizzle-orm'
// Deletar um registro
await db.delete(usuarios).where(eq(usuarios.id, 42))
// Deletar com RETURNING
const [deletado] = await db.delete(usuarios)
.where(eq(usuarios.id, 42))
.returning()
// Deletar varios registros
await db.delete(pedidos).where(eq(pedidos.status, 'cancelado'))
// Deletar com condicoes complexas
await db.delete(notificacoes).where(
and(
eq(notificacoes.lida, true),
lt(notificacoes.dataCriacao, new Date('2024-01-01'))
)
)
// Soft delete
await db.update(usuarios)
.set({ deletadoEm: new Date() })
.where(eq(usuarios.id, 42))
No Lucid (AdonisJS)
// Deletar via model
const usuario = await Usuario.findOrFail(42)
await usuario.delete()
// Deletar via query builder
const deletados = await Usuario.query()
.where('status', 'inativo')
.where('ultimo_login', '<', '2024-01-01')
.delete()
// → deletados = numero de linhas afetadas
// Soft delete com Lucid (usando coluna luxon)
const usuario = await Usuario.findOrFail(42)
usuario.deletadoEm = DateTime.now()
await usuario.save()
// Lucid tem suporte nativo a soft deletes com o mixin SoftDeletes
// No model:
import { compose } from '@adonisjs/core/helpers'
import { SoftDeletes } from 'adonis-lucid-soft-deletes'
export default class Usuario extends compose(BaseModel, SoftDeletes) {
// O mixin adiciona automaticamente:
// - delete() faz soft delete
// - forceDelete() faz hard delete
// - withTrashed() inclui deletados na busca
// - onlyTrashed() busca apenas deletados
// - restore() restaura um registro
}
Exercicios
- Escreva as queries (SELECT de teste + DELETE) para remover todos os logs com mais de 90 dias.
- Delete todos os produtos com estoque zero e que nao foram vendidos nos ultimos 6 meses.
- Implemente soft delete para uma tabela de comentarios: crie a query de "deletar" e a query de "buscar apenas ativos".
- Use RETURNING para deletar notificacoes lidas e retornar quantas foram removidas de cada usuario.
- Implemente o delete do exercicio 2 usando Prisma, Drizzle e Lucid.
Referencias
Testa o que você leu
5 perguntas sobre esta aula. Errar aqui não custa nada - a explicação vem junto da correção.