Desenvolvimento · Banco de dados

SQL básico: as consultas essenciais com exemplos práticos

Edson Feitosa de Oliveira Junior
Edson Feitosa de Oliveira Junior Fundador e Engenheiro Líder · PruPru Digital Services

SQL é a linguagem usada para consultar e alterar dados em bancos relacionais como PostgreSQL, MySQL, SQL Server e SQLite. Com meia dúzia de comandos você já consegue responder perguntas reais do negócio: quais pedidos foram feitos este mês, quanto cada cliente gastou, quais produtos vendem mais.

Neste guia você vai ver SELECT, WHERE, ORDER BY, JOIN, GROUP BY, INSERT, UPDATE e DELETE usando sempre o mesmo exemplo, uma loja com tabelas de clientes e pedidos. No final, os cuidados que evitam o erro mais temido de quem está começando: apagar ou alterar a tabela inteira sem querer.

As tabelas do exemplo

Vamos usar duas tabelas. A de clientes guarda quem compra; a de pedidos guarda cada compra e aponta para o cliente pela coluna cliente_id, que é uma chave estrangeira.

CREATE TABLE clientes (
  id      INTEGER PRIMARY KEY,
  nome    VARCHAR(100) NOT NULL,
  cidade  VARCHAR(60)
);

CREATE TABLE pedidos (
  id          INTEGER PRIMARY KEY,
  cliente_id  INTEGER NOT NULL REFERENCES clientes(id),
  data_pedido DATE NOT NULL,
  valor       DECIMAL(10,2) NOT NULL,
  status      VARCHAR(20) NOT NULL
);

Para praticar sem instalar nada pesado, você pode usar o SQLite (um único arquivo) ou subir um PostgreSQL com Docker, como mostramos em Docker para iniciantes. Os comandos deste artigo funcionam nos principais bancos, com pequenas diferenças apontadas quando existirem.

SELECT, WHERE e ORDER BY: lendo dados

O SELECT escolhe as colunas, o FROM indica a tabela, o WHERE filtra as linhas e o ORDER BY ordena o resultado.

-- Todos os pedidos pagos acima de 100 reais, do maior para o menor
SELECT id, cliente_id, data_pedido, valor
FROM pedidos
WHERE status = 'PAGO'
  AND valor > 100
ORDER BY valor DESC;

Filtros que você vai usar o tempo todo:

Para limitar a quantidade de linhas, PostgreSQL, MySQL e SQLite usam LIMIT 10 no final; o SQL Server usa SELECT TOP 10. Evite SELECT * em código de aplicação: liste as colunas que você realmente precisa.

JOIN: juntando tabelas

Os pedidos só têm o número do cliente. Para mostrar o nome, você junta as duas tabelas pela coluna que as relaciona:

SELECT p.id, c.nome, p.data_pedido, p.valor
FROM pedidos p
INNER JOIN clientes c ON c.id = p.cliente_id
WHERE p.status = 'PAGO';

As letras p e c são apelidos (aliases) que encurtam a escrita. Os dois tipos de JOIN mais usados:

TipoO que retornaExemplo de uso
INNER JOINSó as linhas que têm correspondência nas duas tabelasPedidos com o nome do cliente
LEFT JOINTodas as linhas da tabela da esquerda, com NULL onde não houver correspondênciaTodos os clientes, inclusive os que nunca compraram

Um truque útil com LEFT JOIN: encontrar clientes sem nenhum pedido.

SELECT c.id, c.nome
FROM clientes c
LEFT JOIN pedidos p ON p.cliente_id = c.id
WHERE p.id IS NULL;

GROUP BY e funções de agregação

Quando a pergunta é "quanto", "quantos" ou "qual a média", você agrupa linhas e aplica uma função: COUNT, SUM, AVG, MIN e MAX.

-- Total gasto e quantidade de pedidos por cliente
SELECT c.nome,
       COUNT(p.id)  AS qtd_pedidos,
       SUM(p.valor) AS total_gasto
FROM clientes c
INNER JOIN pedidos p ON p.cliente_id = c.id
WHERE p.status = 'PAGO'
GROUP BY c.nome
HAVING SUM(p.valor) > 500
ORDER BY total_gasto DESC;

Duas regras que confundem no começo:

Em um sistema real, agrupar pelo nome pode juntar dois clientes homônimos. O mais seguro é agrupar por c.id, c.nome.

INSERT, UPDATE e DELETE: alterando dados

Inserir um cliente e um pedido:

INSERT INTO clientes (id, nome, cidade)
VALUES (1, 'Ana Souza', 'Natal');

INSERT INTO pedidos (id, cliente_id, data_pedido, valor, status)
VALUES (10, 1, '2026-10-05', 189.90, 'PENDENTE');

Na prática, o id costuma ser gerado pelo banco (SERIAL ou GENERATED ... AS IDENTITY no PostgreSQL, AUTO_INCREMENT no MySQL, IDENTITY no SQL Server), e você não o informa no INSERT.

Atualizar o status de um pedido:

UPDATE pedidos
SET status = 'PAGO'
WHERE id = 10;

Excluir um pedido:

DELETE FROM pedidos
WHERE id = 10;

Repare que UPDATE e DELETE sempre vêm com WHERE. Sem ele, o comando vale para todas as linhas da tabela.

Cuidados para não apagar dados por engano

Quase todo mundo que trabalha com banco tem uma história de UPDATE sem WHERE. Estes hábitos evitam que a história seja sua:

  1. Escreva o SELECT primeiro. Antes de um UPDATE ou DELETE, rode SELECT COUNT(*) FROM pedidos WHERE ... com o mesmo filtro e confira se a quantidade de linhas faz sentido.
  2. Use transação. Abra com BEGIN (ou START TRANSACTION no MySQL, BEGIN TRANSACTION no SQL Server), rode o comando, confira o número de linhas afetadas e só então faça COMMIT. Se algo estiver errado, ROLLBACK desfaz.
  3. Desconfie do autocommit. Muitas ferramentas gráficas confirmam cada comando automaticamente. Saiba como a sua está configurada.
  4. Não trabalhe direto em produção. Teste em uma cópia ou em ambiente de desenvolvimento. Em produção, use um usuário com permissões limitadas.
  5. Tenha backup testado. Backup que nunca foi restaurado não é garantia. Combine com sua equipe ou com quem administra o servidor uma rotina de backups e de testes de restauração.

Se o banco guarda dados pessoais de clientes, lembre também das obrigações da LGPD para pequenas empresas: quem tem acesso, para quê e por quanto tempo.

Próximos passos

Depois do básico, os temas que mais fazem diferença são índices e leitura do plano de execução, que explicam por que uma consulta demora segundos ou milissegundos. O artigo sobre consultas lentas no MySQL e PostgreSQL é um bom ponto de partida. Se você está aprendendo backend, o passo seguinte é conectar o banco a uma aplicação, como na primeira API com Spring Boot, e ver como uma API serve esses dados, assunto do artigo o que é uma API REST.

Sites e sistemas sob medida

Controle de pedidos, cadastro de clientes e relatórios saem bem melhores quando o banco de dados é bem modelado desde o início. A PruPru desenvolve sistemas web para pequenas empresas com esse cuidado.

Ver serviços →

Perguntas frequentes

Qual banco de dados é melhor para aprender SQL?

Qualquer um dos grandes serve, porque o SQL básico é praticamente igual em todos. PostgreSQL é uma ótima escolha por ser gratuito, muito usado no mercado e seguir o padrão de perto. SQLite é o mais simples para testes rápidos.

Qual a diferença entre WHERE e HAVING?

WHERE filtra as linhas antes do agrupamento e não pode usar funções de agregação. HAVING filtra os grupos depois do GROUP BY e é onde você coloca condições como SUM maior que um valor.

Dá para desfazer um DELETE?

Só se o comando foi executado dentro de uma transação ainda não confirmada, caso em que o ROLLBACK desfaz. Depois do COMMIT, a saída é restaurar um backup, por isso o hábito de conferir com SELECT antes é tão importante.

SQL é uma linguagem de programação?

SQL é uma linguagem de consulta declarativa: você descreve o resultado que quer e o banco decide como buscar. Ela é usada junto com linguagens como Java, Python ou JavaScript, que cuidam da lógica da aplicação.

Falar no WhatsApp agora