Exemplo de diagrama ER: projetando passo a passo o banco de dados de uma loja virtual

Um diagrama ER construído a partir de requisitos: entidades, chaves, cardinalidade pé de galinha, um muitos para muitos via itens do pedido e decisões que valem registro.

· Fundador e desenvolvedor

Publicado em

Exemplo de diagrama ER: projetando passo a passo o banco de dados de uma loja virtual

Um diagrama ER é onde o projeto de um banco de dados é conferido antes de virar migrations. Uma lista de tabelas diz o que existe. O diagrama mostra como as tabelas dependem umas das outras: qual linha precisa de qual, o que pode faltar e onde se esconde um muitos para muitos.

Este guia projeta o banco de dados de uma pequena loja virtual, de requisitos em linguagem simples até um diagrama entidade-relacionamento pronto, e explica a notação conforme ela aparece. A loja é só o exemplo; o método funciona para qualquer esquema.

Quando você precisa de um diagrama ER

Uma lista de tabelas basta quando o esquema tem um punhado de tabelas e um só time trabalha nele. Desenhe o diagrama quando pessoas de fora desse time precisarem entender os dados, quando você revisar um projeto antes de escrever migrations ou quando o esquema tiver crescido a ponto de ninguém mais conseguir guardá-lo de cabeça.

Há duas notações comuns. A notação de Chen, do artigo de Peter Chen de 1976 que apresentou o modelo entidade-relacionamento, desenha entidades como retângulos e relacionamentos como losangos. Ela serve bem à modelagem conceitual. A notação pé de galinha (crow's foot) desenha tabelas como caixas e coloca a cardinalidade nas pontas das linhas. Costuma ser atribuída a Gordon Everest, em 1976, e é a notação usada pela maioria das ferramentas de modelagem de banco de dados. Este guia usa pé de galinha.

Passo 1: requisitos em frases simples

Escreva primeiro as regras como frases. Cada uma vira uma tabela, uma coluna ou uma linha.

  1. Um cliente se cadastra com um endereço de e-mail e pode salvar vários endereços.
  2. Um cliente faz pedidos. Cada pedido é entregue em um dos endereços do cliente.
  3. Um pedido contém um ou mais produtos, cada um com uma quantidade e o preço pago.
  4. Cada produto pertence a uma categoria.
  5. Um pedido pode ter várias tentativas de pagamento, e a maioria tem uma que deu certo.

Passo 2: entidades e chaves

Os substantivos viram entidades: clientes, endereços, pedidos, itens do pedido, produtos, categorias e pagamentos. Cada uma ganha uma chave primária. Use chaves substitutas (uma coluna identity) na maioria das tabelas e chaves naturais únicas onde o negócio já tem uma: o e-mail de um cliente, o SKU de um produto.

Os itens do pedido são a exceção. Um item do pedido não tem identidade própria; ele é a ligação entre um pedido e um produto. A chave primária é o par (order_id, product_id).

Passo 3: relacionamentos e cardinalidade

Cada chave estrangeira é uma linha. Os símbolos em cada ponta dizem quantas linhas podem ficar daquele lado:

Ponta da linha Lê-se Exemplo da loja
Duas barras Exatamente um Cada pedido é feito por exatamente um cliente
Círculo e barra Zero ou um Um pedido tem zero ou uma mensagem de presente, se você incluir uma
Barra e pé de galinha Um ou muitos Um pedido tem um ou muitos itens
Círculo e pé de galinha Zero ou muitos Um cliente tem zero ou muitos pedidos

Leia um relacionamento a partir de uma tabela, ao longo da linha, até o símbolo na outra ponta: "um cliente faz zero ou muitos pedidos", e de volta: "cada pedido é feito por exatamente um cliente".

Uma chave estrangeira NOT NULL significa "exatamente um" do lado referenciado; uma que aceita NULL significa "zero ou um". O "um ou muitos" do outro lado é uma regra de negócio, não algo que uma chave estrangeira garanta, então escreva essa regra no diagrama, onde os leitores vão vê-la.

Passo 4: o muitos para muitos

Pedidos e produtos têm um relacionamento muitos para muitos: um pedido tem muitos produtos, e um produto aparece em muitos pedidos. Bancos relacionais modelam isso com uma tabela no meio. Aqui essa tabela já existe por um motivo melhor do que encanamento: order_items guarda a quantidade e o preço unitário no momento da compra, fatos que pertencem ao par e a nenhum dos lados sozinho.

Passo 5: decisões que vale registrar

Algumas escolhas não aparecem na lista de colunas e causam bugs quando ninguém as conhece:

  • Retrato do preço. order_items.unit_price copia o preço do produto no momento da compra. Mudar um preço depois não pode alterar pedidos antigos.
  • Endereços não são editados no lugar. Quando um pedido aponta para um endereço, editar essa linha reescreveria para onde os pedidos antigos foram. Uma edição cria uma nova linha de endereço.
  • Pagamentos são tentativas. Uma linha por tentativa, com status, para que pagamentos que falharam e foram refeitos continuem visíveis.
  • Dinheiro é numeric. A documentação do PostgreSQL recomenda numeric para valores monetários porque ele é exato.

Passo 6: o DDL

As duas tabelas centrais no PostgreSQL:

CREATE TABLE orders (
  id                  bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  customer_id         bigint NOT NULL REFERENCES customers (id),
  shipping_address_id bigint NOT NULL REFERENCES addresses (id),
  status              text NOT NULL DEFAULT 'pending'
                      CHECK (status IN ('pending', 'paid', 'shipped', 'cancelled')),
  currency            char(3) NOT NULL,
  total               numeric(12,2) NOT NULL CHECK (total >= 0),
  placed_at           timestamptz NOT NULL DEFAULT now()
);

CREATE TABLE order_items (
  order_id   bigint NOT NULL REFERENCES orders (id) ON DELETE CASCADE,
  product_id bigint NOT NULL REFERENCES products (id),
  quantity   integer NOT NULL CHECK (quantity > 0),
  unit_price numeric(12,2) NOT NULL,  -- copied from products.price at checkout
  PRIMARY KEY (order_id, product_id)
);

CREATE INDEX ON orders (customer_id);
CREATE INDEX ON order_items (product_id);

O PostgreSQL não cria sozinho um índice para uma coluna de chave estrangeira, então as duas linhas CREATE INDEX importam para os joins e para exclusões nas tabelas referenciadas. order_items.order_id é coberta pela chave primária, cujo índice começa por ela. ON DELETE CASCADE diz que um item não pode sobreviver ao seu pedido.

O diagrama

Diagrama ER com sete tabelas. Clientes têm endereços e fazem pedidos; cada pedido vai para um endereço, tem um ou mais itens e zero ou mais pagamentos. Cada item aponta para um produto, e cada produto pertence a uma categoria. Uma nota lista as decisões de design.

8 componentes · 7 conexões

Abrir no Archboard
Conteúdo do diagrama
  • customers
  • orders
  • payments
  • addresses
  • order_items
  • products
  • categories
  • belongs to
  • placed by
  • ships to
  • pays for
  • line of
  • for
  • in
O esquema da loja virtual deste guia: clientes, endereços, pedidos, itens do pedido, pagamentos, produtos e categorias, com chaves em todas as tabelas, cardinalidade pé de galinha em todos os relacionamentos e as decisões de design ao lado das tabelas.

Como ler:

  • Clientes (no canto superior esquerdo) têm zero ou muitos endereços e fazem zero ou muitos pedidos.
  • Pedidos (no centro) vão para exatamente um endereço, contêm um ou muitos itens do pedido e têm zero ou muitos pagamentos.
  • Itens do pedido ligam cada pedido a produtos, e cada produto pertence a exatamente uma categoria.
  • A nota traz as decisões do passo 5, ao lado das tabelas que elas afetam.

Como desenhar um diagrama ER legível

  • Nomeie os relacionamentos com verbos. "feito por", "entregue em", "paga" transformam linhas em frases.
  • Marque as chaves nos atributos. Os marcadores PK e FK mostram de relance a qual coluna uma linha pertence.
  • Agrupe as tabelas por domínio. Clientes e endereços, pedidos e pagamentos, o catálogo. Mantenha cada grupo próximo para que as linhas fiquem curtas.
  • Deixe o ruído de fora. Colunas de auditoria como created_by e updated_at, flags de exclusão lógica em todas as tabelas e tabelas técnicas acrescentam linhas sem acrescentar entendimento.
  • Desenhe a tabela do muitos para muitos. Escondê-la atrás de uma linha direta entre pedidos e produtos esconde também a quantidade e o retrato do preço.
  • Mostre as regras de negócio que o esquema não expressa. "Um ou muitos" itens por pedido e "endereços não são editados" são regras que todo mundo precisa conhecer.

Mantenha o diagrama em sincronia com o esquema

Um diagrama ER desenhado à mão fica desatualizado depois da próxima migration. Em vez disso, gere um primeiro rascunho a partir do esquema. A ferramenta gratuita SQL para diagrama ER lê instruções CREATE TABLE ou um pg_dump inteiro e desenha um card por tabela, com marcadores PK, FK e UK e uma linha por chave estrangeira; também há ferramentas para PostgreSQL, Prisma e DBML. As pontas pé de galinha geradas seguem as colunas: uma chave estrangeira NOT NULL é obrigatória e uma que aceita NULL é opcional. Regras que o SQL não contém, como "um ou muitos" itens, você acrescenta à mão.

Monte no Archboard

  1. Entre com Google ou GitHub e crie um diagrama.
  2. Para começar pelo esquema, cole as instruções CREATE TABLE na ferramenta SQL para diagrama ER e selecione Abrir no Archboard. Para desenhar à mão, adicione uma Entidade do pack Entidade-relacionamento para cada tabela, com um atributo por linha e marcadores PK e FK.
  3. Conecte cada chave estrangeira à tabela que ela referencia e configure as pontas das linhas com marcadores pé de galinha: exatamente um na tabela referenciada, zero ou muitos no lado da chave estrangeira e um ou muitos onde uma regra de negócio exigir.
  4. Rotule cada linha com um verbo, como "feito por" ou "entregue em".
  5. Adicione um bloco Markdown do pack Básico com as decisões de design.

O exemplo usa 8 nós de diagrama e fica dentro do plano Free. Para ver como um esquema se encaixa no resto de um sistema, veja o exemplo de diagrama de design de sistemas.

Perguntas frequentes

Qual é a diferença entre um diagrama ER e um diagrama de esquema de banco de dados? Na prática, eles se sobrepõem. Um diagrama ER pode ser conceitual e mostrar entidades e relacionamentos antes de as tabelas existirem; um diagrama de esquema mostra as tabelas, colunas e chaves reais. O diagrama pé de galinha deste guia é as duas coisas.

Toda tabela deve ter uma chave substituta? A maioria das tabelas se beneficia de uma, porque chaves naturais mudam. Tabelas de ligação como order_items costumam usar o par de chaves estrangeiras como chave primária.

Como mostro um relacionamento muitos para muitos? Com a tabela do meio e duas linhas um para muitos. Dê à tabela do meio o nome do que ela representa, como itens do pedido, e não o das duas tabelas que ela liga.

Desenho todas as colunas? Desenhe as chaves e as colunas que explicam o projeto. Deixe de fora colunas de auditoria e técnicas, a menos que o diagrama seja sobre elas.

Chen ou pé de galinha? Chen para conversas conceituais com pessoas que não pensam em tabelas; pé de galinha para tudo o que vai virar um banco de dados.

Comece grátis — um assento, sem cartão de crédito.

Artigos relacionados

← Voltar ao blog

Abra um canvas em um minuto

Entre com Google ou GitHub. Grátis para um assento. Faça upgrade quando a equipe entrar.