Pular para o conteúdo
Cursos

DevClub

LógicaFront-endBack-endMobile

IA Club

IA na prática
Estudar programaçãoEstudar IA

Guia completo

PostgreSQL do zero: guia para aprender banco de dados

Entenda o que o PostgreSQL faz, como tabelas e SQL trabalham juntas e em que ordem estudar consultas, joins, índices, transações e modelagem relacional.

5 lições em trilha5 artigos no guiaAtualizado em agosto de 2026

PostgreSQL é um sistema de banco de dados relacional que guarda informações, aplica regras sobre elas e responde consultas em SQL. Ao terminar este guia, você terá um banco de livraria rodando e um mapa claro do que estudar depois.

O nome técnico completo é sistema gerenciador de banco de dados relacional, ou SGBD relacional. Em português direto: ele é o programa responsável por receber pedidos de leitura e escrita, encontrar os dados, impedir estados inválidos e coordenar várias pessoas ou APIs usando o mesmo banco.

Isso é bem diferente de guardar um array num arquivo. Um arquivo consegue persistir uma lista; o PostgreSQL consegue garantir que dois clientes não usem o mesmo e-mail, que um item nunca aponte para um pedido inexistente e que uma venda com três alterações seja confirmada por inteiro ou desfeita por inteiro. É essa combinação de consulta, regra e coordenação que faz o banco entrar numa aplicação de verdade.

Quando os dados deixam o array e viram responsabilidade do banco

Imagine o catálogo da Livraria Horizonte no começo do projeto. Enquanto existe uma pessoa testando, um array de livros resolve: título, preço e estoque ficam na memória do servidor. O problema aparece quando o processo reinicia, duas compras chegam juntas ou você precisa responder “quais clientes compraram cada livro nos últimos 30 dias?”.

O array não foi uma escolha errada; ele cumpriu a fase de aprendizado. Só não foi criado para ser a fonte compartilhada e durável de uma empresa. O PostgreSQL assume quatro responsabilidades que começam a pesar nesse momento:

  • persistência: os dados sobrevivem ao fim do processo da API;
  • integridade: constraints rejeitam preço negativo, e-mail repetido e referência sem origem;
  • consulta: o banco filtra, agrupa e combina conjuntos sem a aplicação carregar tudo na memória;
  • concorrência: transações coordenam operações simultâneas sem expor uma venda pela metade.

Pense na livraria física. O prédio é o servidor PostgreSQL; uma unidade da loja é um banco; cada ficha organizada é uma linha; os campos impressos na ficha são colunas; e as normas do estoque são constraints. Essa imagem ajuda a localizar as partes. O limite da analogia é importante: o PostgreSQL não percorre prateleiras físicas nem guarda cada tabela num único arquivo simples. Ele usa páginas, buffers, logs e versões de linhas, e decide sozinho boa parte do caminho de leitura.

Servidor, banco, schema e tabela não são quatro nomes para a mesma coisa

Quem começa costuma chamar tudo de “banco”. No trabalho, os quatro níveis aparecem em mensagens de erro e configurações diferentes:

  • o servidor é o processo PostgreSQL aceitando conexões;
  • um database é uma base isolada dentro daquele servidor, como livraria;
  • um schema é um espaço de nomes dentro do database, como public ou financeiro;
  • uma table organiza linhas segundo colunas e regras declaradas.

Uma conexão escolhe um servidor, uma porta, um usuário e um database. Depois disso, a consulta encontra tabelas por schema. É por isso que “o PostgreSQL está rodando” não garante que sua API conectou: ela ainda pode estar usando porta, usuário, senha ou database diferentes.

Outro nome útil é cliente. psql, DBeaver, uma API Node e uma ferramenta de migração são clientes do PostgreSQL. Eles não são o banco; são programas que abrem uma conexão, enviam SQL e recebem linhas, contagens ou erros.

PostgreSQL 18.6 no Docker, sem instalar o servidor na máquina

Para acompanhar o cluster, você precisa de Docker e de um terminal. Este comando cria um container chamado postgres-devclub, define a senha do usuário administrador, cria o database livraria e usa a imagem Alpine da versão 18:

bash
docker run -d \
  --name postgres-devclub \
  -e POSTGRES_PASSWORD=devclub \
  -e POSTGRES_DB=livraria \
  postgres:18-alpine

docker exec postgres-devclub \
  psql -U postgres -d livraria \
  -c "SELECT current_database() AS banco, current_setting('server_version') AS postgresql;"
banco | postgresql ----------+------------ livraria | 18.6 (1 row)

O primeiro comando inicia o servidor; o segundo usa psql dentro do próprio container. A senha curta serve apenas para este laboratório sem porta publicada. Em ambiente real, segredo vai para um gerenciador apropriado, acesso de rede é restrito e o armazenamento precisa sobreviver à troca do container.

Quando quiser entrar no prompt interativo, troque o final por psql -U postgres -d livraria. O texto livraria=# indica que o cliente está pronto para receber SQL. \q encerra o cliente; não derruba o servidor.

As cinco lições usam recortes independentes da mesma Livraria Horizonte para que um erro intencional não estrague a aula seguinte. Execute cada laboratório num database vazio ou num schema descartável; não cole os CREATE TABLE sobre as tabelas de um projeto real.

A primeira prateleira tem estrutura e regra

Vamos criar a tabela central da livraria. CREATE TABLE é uma instrução de definição de dados, também chamada DDL. Ela não cadastra um livro; descreve como todo livro deverá ser guardado.

sql
CREATE TABLE livros (
  id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  titulo text NOT NULL,
  preco numeric(10,2) NOT NULL CHECK (preco > 0),
  estoque integer NOT NULL DEFAULT 0 CHECK (estoque >= 0)
);
CREATE TABLE

O id é a chave primária, a identidade única de cada linha. IDENTITY pede ao PostgreSQL que gere esse número. NOT NULL proíbe ausência, DEFAULT fornece um valor quando a coluna é omitida e CHECK transforma uma regra do negócio em uma barreira do banco.

Pense nessas regras como a conferência na entrada do estoque. A pessoa pode preencher uma ficha, mas ela só entra se tiver identificação, título e valores aceitáveis. O limite da comparação: constraints não entendem toda a operação da empresa. Elas garantem condições declaradas sobre dados; decisões como conceder desconto a um cliente específico ainda pertencem à aplicação ou a uma regra mais explícita.

Agora entram duas linhas. Listar as colunas no INSERT deixa o comando resistente a mudanças de ordem na tabela, e RETURNING devolve o que acabou de ser criado:

sql
INSERT INTO livros (titulo, preco, estoque)
VALUES
  ('Dom Casmurro', 39.90, 8),
  ('A Hora da Estrela', 34.50, 5)
RETURNING id, titulo;
id | titulo ----+------------------- 1 | Dom Casmurro 2 | A Hora da Estrela (2 rows)

INSERT 0 2

Essas linhas já estão persistidas. Não foi necessário pedir save depois: por padrão, cada instrução isolada roda em sua própria transação e é confirmada se termina sem erro.

SQL é o idioma; PostgreSQL é quem executa o trabalho

SQL significa Structured Query Language. É a linguagem declarativa usada para dizer qual resultado você quer. Em vez de programar um laço que visita cada livro, você descreve colunas, filtro e ordem:

sql
SELECT titulo, preco
FROM livros
WHERE estoque > 0
ORDER BY preco;
titulo | preco -------------------+------- A Hora da Estrela | 34.50 Dom Casmurro | 39.90 (2 rows)

SELECT escolhe as colunas do resultado, FROM aponta a origem, WHERE filtra as linhas e ORDER BY ordena o conjunto final. A ordem escrita não descreve um passo a passo de leitura no disco. O planejador do PostgreSQL pode escolher uma varredura da tabela, um índice ou outra estratégia que produza o mesmo resultado.

Essa separação evita uma confusão comum: SQL não é exclusivo do PostgreSQL. MySQL, SQLite, SQL Server e outros bancos relacionais falam dialetos de SQL. O núcleo é parecido, mas tipos, funções, extensões e detalhes de concorrência mudam. RETURNING, por exemplo, faz parte do trabalho diário no PostgreSQL e não deve ser assumido da mesma forma em todo produto.

Como uma consulta vira um plano

Antes de buscar as linhas, o PostgreSQL cria um plano de execução. Pense no atendente decidindo se procura um livro caminhando por toda a loja ou consultando um índice e indo direto à estante. Tabela e índice são as fontes; o planner é quem compara caminhos possíveis.

EXPLAIN mostra a decisão sem executar uma consulta de leitura com ANALYZE:

sql
EXPLAIN (COSTS OFF)
SELECT titulo
FROM livros
WHERE id = 2;
QUERY PLAN ---------------------------------------- Index Scan using livros_pkey on livros Index Cond: (id = 2) (2 rows)

A chave primária criou automaticamente um índice B-tree, então o plano usa livros_pkey. Isso não significa “índice sempre ganha”. Em tabela minúscula ou filtro que devolve quase tudo, percorrer as páginas em sequência pode custar menos. O artigo de índices usa 200 mil pedidos justamente para mostrar uma diferença que o planner considera relevante.

Transação é o recibo que só vale completo

Uma venda não é uma única escrita. Ela pode reduzir estoque, criar pedido, registrar itens e gravar pagamento. Se a terceira etapa falhar, deixar apenas as duas primeiras confirmadas produz um banco que conta histórias contraditórias.

Uma transação agrupa comandos numa unidade de tudo ou nada. Imagine um recibo em elaboração: as linhas podem mudar enquanto ele está aberto, mas a venda só entra no caixa quando o recibo é confirmado. No PostgreSQL, BEGIN abre o bloco, COMMIT confirma e ROLLBACK descarta. A analogia ajuda na atomicidade; ela não explica sozinha isolamento e locks entre conexões, que têm regras próprias.

Aqui a redução aparece dentro da transação e desaparece após o rollback:

sql
BEGIN;
UPDATE livros SET estoque = estoque - 2 WHERE id = 1;
SELECT titulo, estoque FROM livros WHERE id = 1;
ROLLBACK;
SELECT titulo, estoque FROM livros WHERE id = 1;
BEGIN UPDATE 1 titulo | estoque --------------+--------- Dom Casmurro | 6 (1 row)

ROLLBACK titulo | estoque –––––––+——— Dom Casmurro | 8 (1 row)

O primeiro SELECT enxerga a alteração da própria transação. Depois do ROLLBACK, o estoque confirmado continua em oito. Em produção, é a aplicação que decide quando confirmar ou desfazer e sempre devolve a conexão ao pool com a transação encerrada.

Da tela até a linha: por onde uma consulta viaja

Quando a pessoa pesquisa um título no site, o navegador normalmente não fala direto com o PostgreSQL. Ele envia uma requisição HTTP para a API. A API valida a entrada, pega uma conexão disponível, envia uma consulta parametrizada e transforma o resultado numa resposta. O banco fica numa rede protegida e aceita conexões de serviços autorizados, não de qualquer navegador na internet.

Pense numa solicitação que passa pelo balcão antes de chegar ao estoque. A tela descreve o que a pessoa quer; a API confere identidade e formato; a conexão é o canal com o depósito; o SQL é a ordem de busca. De volta ao comportamento técnico, cada etapa tem uma responsabilidade diferente. CHECK (preco > 0) não decide se aquela pessoa pode cadastrar livro, e uma validação da API não impede que outro script grave preço negativo se o banco não tiver constraint.

Essa divisão produz duas camadas de proteção complementares:

  • a aplicação valida formato, autorização e mensagens adequadas para a pessoa;
  • o PostgreSQL preserva invariantes independentemente de qual cliente enviou a escrita.

Valores do usuário entram como parâmetros da biblioteca de banco, nunca por concatenação de texto. Parâmetro separa o comando do dado e evita que uma busca por título vire parte da sintaxe SQL. A forma exata muda entre drivers — $1 é comum no ecossistema Node com PostgreSQL —, mas a regra não muda: o driver envia estrutura e valores sem pedir que você monte aspas na mão.

Uma API também não deve abrir uma conexão nova para cada linha nem manter uma conexão exclusiva para sempre. Um pool de conexões conserva um conjunto limitado de canais e os empresta por operação. O pool reduz o custo de conexão, mas não remove o limite do servidor. Se a aplicação abre mais trabalho simultâneo do que o banco consegue atender, a fila apenas muda de lugar.

O caminho de volta também merece cuidado. A consulta deve devolver somente as colunas necessárias; a API converte tipos quando o driver exige e não expõe hash, token ou dado interno só porque ele estava na linha. Banco relacional organiza e protege dados, mas o contrato HTTP ainda pertence à aplicação.

ORMs entram nessa viagem como tradutores e organizadores. Eles podem gerar consulta, mapear linha para objeto e aplicar migrations. Continuam usando conexões, transações, joins e índices do PostgreSQL. Quando a tela demora ou uma relação duplica resultados, enxergar o SQL gerado e ler o plano continua sendo parte do diagnóstico — por isso esta trilha começa pela linguagem do banco.

Por fim, estrutura também muda com o produto. Uma migration registra, em ordem, a criação ou alteração de tabelas e índices. Ela faz pelo schema o que o Git faz pelo código: deixa uma sequência reproduzível de mudanças. A comparação tem limite — migrations podem alterar dados e travar tabelas, então precisam de revisão, teste e estratégia de retorno; não basta “dar revert” esperando que uma coluna apagada recupere seu conteúdo.

O mapa do cluster: cinco problemas que aparecem em ordem

Aprender banco por uma lista de comandos soltos cria uma falsa sensação de progresso. A ordem abaixo parte do dado numa tabela, conecta tabelas, mede acesso, protege operações e só então volta ao desenho inteiro.

etapa pergunta que você resolve lição do cluster
1. operar uma tabela como cadastrar, buscar, alterar e excluir sem atingir linhas erradas? SELECT, INSERT, UPDATE e DELETE
2. relacionar como mostrar livro, autor, pedido e cliente no mesmo resultado? JOIN no PostgreSQL
3. encontrar em escala como conferir se uma consulta percorre 200 mil linhas e quando criar índice? índices e EXPLAIN
4. confirmar tudo junto como impedir pedido salvo sem estoque atualizado? transações, rollback e locks
5. desenhar antes de crescer onde ficam chaves, relações muitos-para-muitos e regras de integridade? modelagem relacional

Essa sequência não transforma a modelagem em assunto menos importante. Ela permite que você sinta o problema antes de receber o nome. Depois de escrever um JOIN, a utilidade da chave estrangeira deixa de ser abstrata. Depois de ver uma operação pela metade, a transação deixa de parecer cerimônia.

A minha régua para escolher PostgreSQL

Eu escolheria PostgreSQL como padrão para uma API que guarda clientes, pedidos, pagamentos, agenda, estoque ou qualquer dado com relações e regras. Ele oferece SQL expressivo, constraints, transações maduras, índices variados e uma comunidade grande. Para boa parte dos produtos, a pergunta não é se ele aguenta; é se o time modelou e consultou bem.

Isso não faz dele resposta universal. Um arquivo SQLite pode ser melhor para uma ferramenta local com uma pessoa usando. Armazenamento de objetos é melhor para vídeos e imagens grandes. Um mecanismo de busca pode complementar pesquisa textual avançada. Cache em memória pode aliviar leituras repetidas. Em sistemas reais, essas ferramentas convivem; não precisam disputar o mesmo papel.

situação ponto de partida motivo
API com clientes, pedidos e pagamento PostgreSQL relações, constraints e transações são centrais
aplicação local, arquivo único, um processo SQLite operação menor e nenhum servidor separado
foto, vídeo e arquivo de usuário object storage + referência no PostgreSQL banco guarda metadado; objeto guarda bytes grandes
consulta textual muito especializada em escala PostgreSQL primeiro; mecanismo de busca quando medido evita adicionar infraestrutura antes do gargalo existir
resposta muito repetida e descartável PostgreSQL como fonte + cache cache acelera, mas não vira fonte da verdade

“PostgreSQL primeiro” não significa criar extensão, réplica e vinte índices no primeiro dia. Significa começar com uma fonte da verdade capaz de proteger o dado e acrescentar complexidade quando uma medição exigir.

As decisões que poupam uma reforma depois

Alguns hábitos valem desde a primeira tabela:

  1. Dê chave primária a toda entidade. Um título pode mudar e um e-mail pode ser corrigido; a identidade da linha precisa continuar estável.
  2. Use tipos que representam o dado. Dinheiro pede numeric, instante pede timestamptz, quantidade pede inteiro. Texto não é um recipiente neutro para tudo.
  3. Coloque invariantes no banco. NOT NULL, UNIQUE, CHECK e FOREIGN KEY protegem todas as aplicações que escrevem ali, não apenas a tela atual.
  4. Liste colunas em escrita e leitura de aplicação. INSERT sem nomes e SELECT * dependem de uma estrutura que vai mudar.
  5. Crie índice a partir de consulta real. O índice tem custo de disco e de escrita; EXPLAIN mostra se o caminho mudou.
  6. Envolva passos inseparáveis numa transação. Se você não consegue aceitar metade da operação, o banco também não deve aceitar.
  7. Versione mudanças com migrations. Alterar uma tabela manualmente em cada ambiente produz bancos parecidos, não iguais.

Um ORM ajuda a aplicar parte disso, mas não elimina nenhuma decisão. Ele troca SQL escrito à mão por uma API e gera SQL no final. Quando uma relação, índice ou transação se comporta diferente do esperado, o diagnóstico volta para o modelo do PostgreSQL.

Para acompanhar esse caminho dentro de uma aplicação, o tutorial API Node com TypeScript, Express, Prisma e Docker mostra migrations, constraints e consultas reais antes de provar o CRUD por HTTP.

Missão: tire um catálogo da memória e coloque sob regras

Crie um database de estudo e uma tabela livros com id, titulo, preco e estoque. Cadastre três livros, consulte apenas os que têm estoque e tente salvar um preço negativo. O critério de sucesso tem três partes: o SELECT devolve somente as linhas esperadas, a tentativa inválida recebe um erro de constraint e um novo SELECT prova que nenhuma linha ruim entrou.

Depois, desenhe num papel as próximas tabelas da Livraria Horizonte: autores, clientes, pedidos e itens. Não adicione todas agora. Marque apenas quem possui identidade própria e escreva ao lado onde existe “um para muitos” ou “muitos para muitos”. Você vai comparar esse rascunho com a lição de modelagem no fim da trilha.

O próximo passo concreto é praticar as quatro operações numa tabela só em SELECT, INSERT, UPDATE e DELETE. Quando cada comando tiver um resultado observável, o JOIN deixa de ser uma parede de sintaxe e vira apenas a forma de reencontrar partes relacionadas.

Trilha

Banco de dados

SQL, PostgreSQL, MongoDB e Prisma: modelar, consultar e conectar o banco na API que você escreveu.

Ver a trilha
  1. 01SQL: SELECT, INSERT, UPDATE e DELETE no PostgreSQL
  2. 02JOIN no PostgreSQL: combine tabelas sem perder linhas
  3. 03Modelagem relacional no PostgreSQL: tabelas e chaves
  4. 04Índices no PostgreSQL: crie e confirme com EXPLAIN
  5. 05Transações no PostgreSQL: COMMIT, ROLLBACK e locks

Perguntas frequentes

Preciso saber programação antes de aprender PostgreSQL?
Não. Você pode aprender tabela, chave e SQL sem escrever uma API. Saber variáveis e tipos ajuda, mas o melhor começo é consultar e alterar um banco pequeno diretamente pelo psql.
PostgreSQL e SQL são a mesma coisa?
Não. SQL é a linguagem usada para consultar e alterar dados relacionais. PostgreSQL é o sistema que recebe essa linguagem, guarda os dados, escolhe planos de execução e protege transações e regras.
PostgreSQL serve para projeto pequeno?
Serve. Um projeto pequeno ganha constraints, transações e consultas poderosas desde o começo. O custo é precisar executar e cuidar de um serviço de banco, mesmo que ele esteja num container.
Devo aprender ORM antes de SQL?
Não. Aprenda primeiro SELECT, INSERT, UPDATE, DELETE, JOIN e transação. O ORM gera ou organiza essas operações; sem SQL você fica sem vocabulário para entender uma consulta lenta ou uma relação configurada errado.
Qual versão do PostgreSQL devo usar para estudar?
Use uma versão suportada e próxima da produção. Os exemplos deste cluster foram executados no PostgreSQL 18.6, imagem postgres:18-alpine, mas os fundamentos mostrados também existem nas versões suportadas anteriores.

O código deste guia foi executado em PostgreSQL 18.6 em postgres:18-alpine e Docker 29.5.3, e as saídas exibidas são as reais — como produzimos este conteúdo.

Fontes consultadas

  1. PostgreSQL 18 — Tutorial oficial — postgresql.org
  2. PostgreSQL 18 — A linguagem SQL — postgresql.org
  3. PostgreSQL 18 — Definição de dados — postgresql.org
  4. PostgreSQL 18 — Release 18.6 — postgresql.org