As quatro operações DML do SQL — INSERT, SELECT, UPDATE e DELETE — que formam a base de qualquer CRUD. Cada episódio mostra a sintaxe da operação, os modificadores principais e variações úteis em PostgreSQL, usando a tabela departamento.produto como exemplo recorrente.
As 4 operações DML, o que é DML vs DDL e a tabela departamento.produto que serve de exemplo
CRUD = Create, Read, Update, Delete — as quatro operações fundamentais sobre os dados de uma tabela. Em SQL, cada uma corresponde a um comando DML (Data Manipulation Language): INSERT, SELECT, UPDATE e DELETE.
DML vs DDL: DML mexe nos dados (linhas) — é o foco deste guia. DDL mexe na estrutura (tabelas, colunas, índices): CREATE TABLE, ALTER TABLE, DROP TABLE. DDL roda uma vez no setup; DML roda o tempo todo no fluxo do app.
Os exemplos da página todos rodam contra a tabela departamento.produto — schema departamento, PK id_produto serial, mais nome, valor, quantidade e observação. O DDL completo (CREATE SCHEMA + CREATE TABLE) está no CÓDIGO COMPLETO desta seção pra você poder reproduzir no PRD_TREINAMENTO.
INSERT INTO — adicionar uma ou várias linhas, DEFAULT pra serial, RETURNING pra capturar o id
Sintaxe básica: INSERT INTO tabela (col1, col2, ...) VALUES (val1, val2, ...). As colunas listadas têm que casar 1-pra-1 com os valores; colunas omitidas recebem o DEFAULT da definição (NULL se não houver, ou o próximo valor da sequence pra serial).
Múltiplas linhas: separe os VALUES por vírgula — INSERT INTO produto (...) VALUES (...), (...), (...). Mais rápido que N inserts separados porque o banco só faz um round-trip e um WAL flush.
RETURNING: extensão do PostgreSQL que retorna colunas das linhas inseridas. Padrão pra capturar o id_produto gerado pelo serial sem precisar de um SELECT depois — INSERT INTO produto(...) VALUES(...) RETURNING id_produto. Também aceita RETURNING * ou expressões.
INSERT ... SELECT: copia dados de outra fonte — INSERT INTO produto (nome_produto, vl_produto) SELECT nome, valor FROM outra_tabela WHERE .... Útil pra migração ou backfill.
SELECT — projeção (colunas), filtro (WHERE), ordenação (ORDER BY), agregação (GROUP BY) e paginação (LIMIT)
Sintaxe básica: SELECT colunas FROM tabela WHERE condição ORDER BY coluna LIMIT n. SELECT * traz todas as colunas — prático em ad-hoc, evite em código de produção (mudar a tabela quebra ordem).
WHERE: operadores =, <>, <, >, <=, >=, BETWEEN ... AND ..., IN (...), LIKE (case-sensitive, % = qualquer string, _ = um caractere), ILIKE (case-insensitive — extensão PostgreSQL), IS NULL / IS NOT NULL. Combine com AND / OR e parênteses.
ORDER BY: uma ou várias colunas — ORDER BY nome_produto ASC, vl_produto DESC. ASC é o padrão. NULLS FIRST / NULLS LAST controla onde nulos caem.
Agregadores: COUNT(*), SUM(col), AVG(col), MIN(col), MAX(col). Combinados com GROUP BY: SELECT qtd_produto, COUNT(*) FROM produto GROUP BY qtd_produto. HAVING filtra grupos depois do agregador (WHERE filtra linhas antes).
Paginação: LIMIT n OFFSET m — retorna n linhas pulando as primeiras m. Sempre combine com ORDER BY ou a ordem é indefinida.
UPDATE...SET...WHERE — atualizar uma ou várias colunas, expressões com a coluna atual, RETURNING e o perigo de esquecer o WHERE
Sintaxe básica: UPDATE tabela SET col1 = val1, col2 = val2 WHERE condição. Várias colunas em uma chamada separadas por vírgula no SET.
Sem WHERE atualiza TUDO. Esse é o erro mais clássico — UPDATE produto SET vl_produto = 0 zera o valor de todos os produtos. Em produção, sempre use uma transação (BEGIN; UPDATE ...; ROLLBACK pra testar) ou rode primeiro um SELECT com o mesmo WHERE pra ver quantas linhas vão ser afetadas.
Expressões: o lado direito do = pode ser uma expressão envolvendo a própria coluna. Exemplo: reajuste de 10% nos preços — UPDATE produto SET vl_produto = vl_produto * 1.10 WHERE qtd_produto > 0. Também aceita funções (upper(nome_produto), now(), etc).
RETURNING: assim como no INSERT, retorna as linhas atualizadas — útil pra capturar o estado novo. UPDATE produto SET vl_produto = vl_produto * 1.10 WHERE id_produto = 1 RETURNING id_produto, vl_produto.
UPDATE ... FROM: extensão do PostgreSQL pra atualizar usando dados de outra tabela — UPDATE produto SET vl_produto = nova.valor FROM tabela_reajuste nova WHERE produto.id_produto = nova.id.
DELETE FROM...WHERE — excluir registros, FK constraints, TRUNCATE como alternativa, RETURNING pra ver o que saiu
Sintaxe básica: DELETE FROM tabela WHERE condição. Mesmo perigo do UPDATE — sem WHERE deleta TUDO. Em produção, transação primeiro: BEGIN; DELETE ...; -- conferir count; COMMIT ou ROLLBACK.
FK constraint violation: se outra tabela referencia o registro via foreign key, o DELETE falha por padrão (ON DELETE NO ACTION ou RESTRICT). O Jasap captura isso como SQLConstraintException e mostra Toast vermelho ("registro está sendo usado em outra tabela"). Pra cascatear, a FK precisa ter sido criada com ON DELETE CASCADE.
TRUNCATE: alternativa pra limpar a tabela inteira — TRUNCATE TABLE produto. Muito mais rápido que DELETE sem WHERE porque não escreve cada linha no WAL, mas: não dispara triggers BEFORE/AFTER DELETE, não respeita ON DELETE de FKs (use CASCADE explícito), e reseta a sequence do serial se você passar RESTART IDENTITY.
RETURNING: mesmo padrão de INSERT/UPDATE — retorna as linhas excluídas. DELETE FROM produto WHERE qtd_produto = 0 RETURNING id_produto, nome_produto diz o que sumiu.
DELETE ... USING: extensão PostgreSQL pra deletar com base em outra tabela — DELETE FROM produto USING tabela_obsoletos o WHERE produto.id_produto = o.id.