Além de consultar dados com SELECT, o SQL permite modificar o conteúdo de um banco de dados por meio de três comandos DML: INSERT (inserir), DELETE (excluir) e UPDATE (atualizar).
INSERT: Inserindo Dados
Inserção de uma única linha
A forma mais simples insere uma linha com valores explícitos:
-- Inserir um novo centro na UnDFINSERTINTO centro (id_centro, sigla, nome_centro)VALUES (4, 'COLAB', 'Centro de Laboratórios Avançados');
Ao inserir uma escola vinculada ao novo centro:
INSERTINTO escola (id_escola, sigla, nome_escola, id_centro)VALUES (41, 'ELAB', 'Escola de Laboratórios', 4);
INSERT com SELECT
É possível inserir dados copiados de outra tabela com base em uma consulta. Suponha a existência de uma tabela disciplina_historico com a mesma estrutura de disciplina:
-- Criar tabela histórica (estrutura idêntica a disciplina)CREATETABLE disciplina_historico ( id_disciplina INTEGERPRIMARYKEY, nome_disciplina VARCHAR(100) NOTNULL, id_curso INTEGER, semestre INTEGER, carga_horaria INTEGER);-- Copiar para o histórico as disciplinas com carga horária acima de 150 hINSERTINTO disciplina_historicoSELECT*FROM disciplinaWHERE carga_horaria >150;
Verificando o que seria inserido:
-- Disciplinas que seriam copiadas para o histórico (carga > 150 h)SELECT id_disciplina, nome_disciplina, id_curso, carga_horariaFROM disciplinaWHERE carga_horaria >150ORDERBY carga_horaria DESC;
2 records
id_disciplina
nome_disciplina
id_curso
carga_horaria
3110401
Bases da Eng. de Software 4
311
180
3110802
Projeto Aplicado 8 - Sistema em Tempo Real
311
160
DELETE: Excluindo Dados
DELETE simples
-- Remover disciplinas de semestres ímpares (não fazem parte da nossa amostra)DELETEFROM disciplinaWHERE semestre % 2=1;
DELETE com subconsulta
Para condições mais complexas, o WHERE pode conter subconsultas:
-- Remover matrículas de alunos com nota abaixo de 5.0 em todas as disciplinasDELETEFROM matricula_disciplinaWHERE id_aluno IN (SELECT id_alunoFROM matricula_disciplinaGROUPBY id_alunoHAVINGAVG(nota) <5.0);
Verificando quais alunos seriam afetados:
-- Alunos com média abaixo de 5.0SELECT id_aluno, ROUND(AVG(nota), 2) AS mediaFROM matricula_disciplinaGROUPBY id_alunoHAVINGAVG(nota) <5.0;
2 records
id_aluno
media
2024311002
4.9
2025311002
4.0
Aviso
DELETE sem WHERE remove todas as linhas da tabela. Sempre verifique com um SELECT primeiro quais linhas serão afetadas antes de executar o DELETE.
UPDATE: Atualizando Dados
UPDATE simples
-- Renomear um curso (corrigir nome)UPDATE cursoSET nome_curso ='Engenharia de Software (Bacharelado)'WHERE id_curso =311;
UPDATE condicional
-- Aumentar carga horária das disciplinas de semestre 8 em 10%UPDATE disciplinaSET carga_horaria =ROUND(carga_horaria *1.10)WHERE semestre =8;
Verificando o que seria alterado:
-- Disciplinas de semestre 8 e como ficariam com +10% de carga horáriaSELECT id_disciplina, nome_disciplina, carga_horaria AS carga_atual,ROUND(carga_horaria *1.10) AS carga_novaFROM disciplinaWHERE semestre =8ORDERBY id_curso;
6 records
id_disciplina
nome_disciplina
carga_atual
carga_nova
1110801
Monografia
100
110
1110802
Desenvolvimento Econômico
90
99
2110801
Tecnologia Educacional - Design
60
66
2110802
Estatística Aplicada
50
55
3110801
Bases da Eng. de Software 8
100
110
3110802
Projeto Aplicado 8 - Sistema em Tempo Real
160
176
UPDATE com CASE: reajuste diferenciado
Quando diferentes grupos de linhas precisam de atualizações diferentes, o CASE permite aplicar regras distintas em um único comando:
-- Ajuste de carga horária por faixa:-- Disciplinas com carga <= 60 h → aumentar 20%-- Disciplinas com carga > 60 h → aumentar 10%UPDATE disciplinaSET carga_horaria =CASEWHEN carga_horaria <=60THENROUND(carga_horaria *1.20)ELSEROUND(carga_horaria *1.10)END;
Verificando o efeito por faixa:
-- Simular o ajuste sem alterar o bancoSELECT id_disciplina, id_curso, carga_horaria AS atual,CASEWHEN carga_horaria <=60THENROUND(carga_horaria *1.20)ELSEROUND(carga_horaria *1.10)ENDAS propostoFROM disciplinaORDERBY id_curso, semestre;
Displaying records 1 - 10
id_disciplina
id_curso
atual
proposto
1110201
111
75
83
1110202
111
60
72
1110401
111
75
83
1110402
111
95
105
1110601
111
75
83
1110602
111
75
83
1110801
111
100
110
1110802
111
90
99
2110201
211
60
72
2110202
211
60
72
Vantagem do CASE em UPDATE:
O uso de um único UPDATE com CASE garante que o ajuste seja calculado com base nos valores originais — não há risco de uma linha receber o primeiro ajuste e depois entrar na faixa errada do segundo. Isso é diferente de usar dois UPDATEs separados.
UPDATE com subconsulta
-- Marcar como aprovadas todas as matrículas com nota >= 6.0UPDATE matricula_disciplinaSET aprovado =1WHERE nota >=6.0AND aprovado ISNULL;
Verificando o estado atual:
-- Distribuição de aprovados e reprovadosSELECT aprovado,COUNT(*) AS n_registros,ROUND(AVG(nota), 2) AS nota_mediaFROM matricula_disciplinaGROUPBY aprovadoORDERBY aprovado;
2 records
aprovado
n_registros
nota_media
0
7
2.24
1
51
7.47
Resumo dos Comandos de Modificação
Comando
Ação
Cuidado
INSERT INTO ... VALUES
Insere linhas com valores explícitos
Respeitar restrições (PK, FK, NOT NULL, CHECK)
INSERT INTO ... SELECT
Insere linhas copiadas de uma consulta
A consulta deve retornar colunas compatíveis
DELETE FROM ... WHERE
Remove linhas que satisfazem a condição
Sem WHERE, remove todas as linhas
UPDATE ... SET ... WHERE
Atualiza colunas das linhas que satisfazem a condição
Sem WHERE, atualiza todas as linhas
Para Praticar
-- Simular: quais professores seriam afetados por um reajuste de 15%-- para quem tem salário abaixo da média?SELECT nome, id_escola, salario AS atual,ROUND(salario *1.15, 2) AS apos_reajusteFROM professorWHERE salario < (SELECTAVG(salario) FROM professor)ORDERBY salario;
3 records
nome
id_escola
atual
apos_reajuste
Igor Melo
31
3100
3565
Eduarda Souza
21
3200
3680
Gustavo Costa
31
3300
3795
-- Simular: disciplinas que seriam removidas se excluíssemos as sem pré-requisitos-- e sem matrícula (seguras para remover)SELECT d.id_disciplina, d.nome_disciplina, d.id_cursoFROM disciplina dWHERE d.id_disciplina NOTIN (SELECT id_disciplina FROM prereq)AND d.id_disciplina NOTIN (SELECT id_prereq FROM prereq)AND d.id_disciplina NOTIN (SELECTDISTINCT id_disciplina FROM matricula_disciplina)ORDERBY d.id_curso, d.id_disciplina;
2 records
id_disciplina
nome_disciplina
id_curso
1110802
Desenvolvimento Econômico
111
2110802
Estatística Aplicada
211
-- Violação de FK: tentar deletar uma disciplina que tem pré-requisitos-- Isso geraria erro:DELETEFROM disciplina WHERE id_disciplina =3110201;-- ERROR: update or delete on table "disciplina" violates foreign key constraint-- "prereq_id_prereq_fkey" on table "prereq"-- DETAIL: Key (id_disciplina)=(3110201) is still referenced from table "prereq".-- Solução: deletar os pré-requisitos primeiro, ou usar CASCADEDELETEFROM prereq WHERE id_disciplina =3110201OR id_prereq =3110201;DELETEFROM disciplina WHERE id_disciplina =3110201;-- (não executar — apenas ilustrativo)
Aviso
Ordem importa no DELETE com FKs. Ao remover dados em tabelas com chaves estrangeiras, é preciso excluir primeiro as linhas das tabelas referenciantes antes das referenciadas. Alternativamente, defina a FK com ON DELETE CASCADE para que o banco faça isso automaticamente — mas use com cautela em produção.