DML — Modificação de Dados
Aula 6 de 8
INSERT
-- Simples
INSERT INTO clientes (nome, email, telefone)
VALUES ('João Silva', '[email protected]', '11999999999');
-- Múltiplos registros
INSERT INTO clientes (nome, email) VALUES
('Maria', '[email protected]'),
('Carlos', '[email protected]'),
('Ana', '[email protected]');
-- INSERT com SELECT
INSERT INTO clientes_premium (id, nome, email, total_gasto)
SELECT c.id, c.nome, c.email, SUM(p.total) AS total_gasto
FROM clientes c
JOIN pedidos p ON p.cliente_id = c.id
GROUP BY c.id, c.nome, c.email
HAVING SUM(p.total) > 10000;
-- INSERT ... ON CONFLICT (PostgreSQL)
INSERT INTO clientes (email, nome, telefone)
VALUES ('[email protected]', 'João Atualizado', '11988888888')
ON CONFLICT (email)
DO UPDATE SET nome = EXCLUDED.nome, telefone = EXCLUDED.telefone;
-- INSERT IGNORE (MySQL)
INSERT IGNORE INTO clientes (email, nome) VALUES ('[email protected]', 'João');
UPDATE
-- CUIDADO: sem WHERE, atualiza TODAS as linhas!
UPDATE clientes SET ativo = true;
-- Com filtro
UPDATE clientes
SET telefone = '11977777777',
data_atualizacao = CURRENT_TIMESTAMP
WHERE id = 10;
-- UPDATE com JOIN (PostgreSQL)
UPDATE pedidos p
SET status = 'cancelado'
FROM clientes c
WHERE p.cliente_id = c.id
AND c.ativo = false
AND p.status = 'pendente';
-- UPDATE com subquery
UPDATE produtos
SET preco_venda = preco_venda * 1.1
WHERE categoria_id IN (
SELECT id FROM categorias WHERE nome = 'Eletrônicos'
);
DELETE
-- CUIDADO: sem WHERE, deleta TUDO!
DELETE FROM pedidos WHERE id = 100;
-- DELETE com JOIN (PostgreSQL)
DELETE FROM pedidos p
USING clientes c
WHERE p.cliente_id = c.id AND c.ativo = false;
-- TRUNCATE (mais rápido que DELETE, não pode ter WHERE)
TRUNCATE TABLE logs_temporarios;
-- Delete em lotes (evitar locks longos)
DELETE FROM pedidos
WHERE data_pedido < '2020-01-01'
LIMIT 1000; -- PostgreSQL suporta LIMIT em DELETE
MERGE (Upsert)
-- PostgreSQL: INSERT ON CONFLICT
INSERT INTO estoque (produto_id, quantidade)
VALUES (1, 50)
ON CONFLICT (produto_id)
DO UPDATE SET quantidade = EXCLUDED.quantidade;
-- MySQL: INSERT ON DUPLICATE KEY
INSERT INTO estoque (produto_id, quantidade) VALUES (1, 50)
ON DUPLICATE KEY UPDATE quantidade = VALUES(quantidade);
-- SQL Server: MERGE
MERGE estoque AS target
USING (VALUES (1, 50)) AS source (produto_id, quantidade)
ON target.produto_id = source.produto_id
WHEN MATCHED THEN UPDATE SET quantidade = source.quantidade
WHEN NOT MATCHED THEN INSERT (produto_id, quantidade) VALUES (source.produto_id, source.quantidade);
Lab: Data Cleaning
-- Identificar duplicatas
SELECT email, COUNT(*), MIN(id) AS manter_id
FROM clientes
GROUP BY email
HAVING COUNT(*) > 1;
-- Remover duplicatas mantendo o primeiro registro
DELETE FROM clientes
WHERE id NOT IN (
SELECT MIN(id)
FROM clientes
GROUP BY email
);
-- Atualizar dados inconsistentes
UPDATE produtos
SET preco_venda = preco_custo * 1.3
WHERE preco_venda <= preco_custo;
-- Soft delete (melhor que DELETE físico)
ALTER TABLE clientes ADD COLUMN deletado_em TIMESTAMP;
UPDATE clientes SET deletado_em = CURRENT_TIMESTAMP WHERE id = 5;
-- Queries: WHERE deletado_em IS NULL
INSERT, UPDATE, DELETE são operações de escrita. Sempre use WHERE ou confirme que quer TODAS as linhas. Prefira soft delete (coluna deletado_em) a DELETE físico. TRUNCATE é mais rápido que DELETE para limpar tabelas.