Editor de diagrama ER Mermaid
Um diagrama entidade-relacionamento mostra tabelas, suas colunas e como elas se juntam. Use quando o assunto for um esquema de banco de dados e as perguntas interessantes forem sobre chaves e cardinalidade — um para muitos, opcional, ou através de uma tabela associativa. Para tipos com comportamento e herança, use um diagrama de classes.
Um esquema de pedidos normalizado com tabela associativa
A parte que merece estudo é o `}o--||` de ITEM_PEDIDO: é assim que se expressa com honestidade um relacionamento muitos-para-muitos, através de uma tabela associativa com colunas próprias, em vez de fingir que duas tabelas se ligam diretamente. Guardar o preço no item, e não só no produto, é a decisão que o diagrama precisa deixar visível.
erDiagram
CLIENTE ||--o{ PEDIDO : "realiza"
PEDIDO ||--|{ ITEM_PEDIDO : "contém"
PRODUTO ||--o{ ITEM_PEDIDO : "aparece em"
CLIENTE ||--o{ ENDERECO : "entrega em"
CLIENTE {
int id PK
string email UK "gravado em minúsculas"
string nome
datetime criado_em
}
PEDIDO {
int id PK
int cliente_id FK
string status
decimal valor_total
}
ITEM_PEDIDO {
int pedido_id PK, FK
int produto_id PK, FK
int quantidade
decimal preco_unitario "preço no momento do pedido"
}
PRODUTO {
int id PK
string sku UK
string nome
}
ENDERECO {
int id PK
int cliente_id FK
string cep
}Exemplos resolvidos
1. Duas entidades e um relacionamento
Todo relacionamento ER precisa de um rótulo depois dos dois-pontos — não é opcional, ao contrário de uma aresta de fluxograma. Leia como uma frase: CLIENTE realiza PEDIDO.
erDiagram
CLIENTE ||--o{ PEDIDO : "realiza"2. Acrescentar colunas
Cada linha de atributo é `tipo nome`, e as duas partes são obrigatórias. `PK`, `FK` e `UK` marcam chaves; uma string entre aspas no fim é um comentário.
erDiagram
CLIENTE ||--o{ PEDIDO : "realiza"
CLIENTE {
int id PK
string email UK
string nome
}
PEDIDO {
int id PK
int cliente_id FK
datetime feito_em "em UTC"
}3. Cardinalidade que diz alguma coisa
Os dois caracteres mais próximos de cada entidade são a cardinalidade dela. Este exemplo diz que um pedido precisa ter ao menos um item, mas que um cliente pode não ter pedido nenhum: uma restrição real, que o esquema deveria impor e o diagrama deveria mostrar.
erDiagram
CLIENTE ||--o{ PEDIDO : "realiza"
PEDIDO ||--|{ ITEM_PEDIDO : "contém"
ITEM_PEDIDO }o--|| PRODUTO : "referencia"4. Muitos-para-muitos com tabela associativa
O Mermaid consegue desenhar um muitos-para-muitos direto, mas um esquema quase nunca tem um: há uma tabela associativa por baixo. Desenhá-la é mais honesto e dá onde colocar as colunas que pertencem ao próprio relacionamento.
erDiagram
ALUNO ||--o{ MATRICULA : "se inscreve em"
DISCIPLINA ||--o{ MATRICULA : "é cursada via"
MATRICULA {
int aluno_id PK, FK
int disciplina_id PK, FK
datetime matriculado_em
string nota "nula até a avaliação"
}
ALUNO {
int id PK
string nome
}
DISCIPLINA {
int id PK
string codigo UK
}5. Relacionamentos reflexivos
Uma tabela pode se relacionar consigo mesma: uma linha de subordinação, uma árvore de categorias, uma thread de comentários. Aqui o rótulo do relacionamento importa mais que o normal, porque as duas pontas são a mesma entidade.
erDiagram
FUNCIONARIO ||--o{ FUNCIONARIO : "gerencia"
FUNCIONARIO {
int id PK
int gestor_id FK "nulo para a diretoria"
string nome
string cargo
}Referência de sintaxe do diagrama ER
A cardinalidade é escrita com dois caracteres em cada ponta do relacionamento e se lê do centro para fora. O par da esquerda descreve a entidade da esquerda; o da direita, a da direita.
| Sintaxe | Significado |
|---|---|
| erDiagram | Abre o diagrama. Diferencia maiúsculas: `erdiagram` não vale. |
| A ||--o{ B : "rótulo" | Relacionamento. O rótulo é obrigatório. |
| || | Exatamente um. |
| o| | Zero ou um. |
| }| | Um ou mais. |
| }o | Zero ou mais. |
| -- | Relacionamento identificador — linha cheia. |
| .. | Relacionamento não identificador — linha tracejada. |
| A { ... } | Bloco de atributos da entidade A. |
| int id PK | Atributo: tipo, depois nome, depois marca de chave opcional. |
| PK / FK / UK | Chave primária, estrangeira, única. |
| int id PK, FK | Várias marcas de chave, separadas por vírgula. |
| string email "comentário" | A string entre aspas no fim é um comentário da coluna. |
| A ||--o{ B : "pertence a" | As aspas são OBRIGATÓRIAS assim que o rótulo tiver um espaço. Sem elas ele é cortado no primeiro espaço e cada palavra restante vira uma entidade fantasma. |
Seis erros que quebram um diagrama ER
O ER tem a gramática mais rígida dos seis tipos: o que passa em outros diagramas aqui é rejeitado de cara. Mas é também onde mora a falha silenciosa que mais castiga quem escreve em português. Tudo reproduzido no Mermaid 11.12.2.
O que você vê
Desenha, o rótulo sai cortado e surgem entidades que você não escreveu
Por quê
Um rótulo de relacionamento com espaço e sem aspas. É a falha que mais vai incomodar em português, porque quase todos os nossos verbos de relação pedem preposição: «pertence a», «aparece em», «entrega em». Medido: `CLIENTE ||--o{ PEDIDO : pertence a` não dá erro nenhum, corta o rótulo para «pertence» e cria uma entidade fantasma chamada «a». Com três palavras saem duas entidades fantasma. Duas tabelas viram quatro caixas e nada avisa.
Solução
Ponha entre aspas todo rótulo que tiver espaço. Em português isso significa quase sempre; é mais fácil adotar como regra do que decidir caso a caso.
erDiagram
CLIENTE ||--o{ PEDIDO : pertence aerDiagram
CLIENTE ||--o{ PEDIDO : "pertence a"O que você vê
Parse error, terminando em: Expecting 'COLON', 'STYLE_SEPARATOR', got 'NEWLINE'
Por quê
Um relacionamento sem rótulo. Ao contrário de uma aresta de fluxograma, os dois-pontos e o rótulo são obrigatórios: sem eles a linha simplesmente termina cedo demais.
Solução
Acrescente os dois-pontos e uma locução verbal, entre aspas se tiver espaço.
erDiagram
CLIENTE ||--o{ PEDIDOerDiagram
CLIENTE ||--o{ PEDIDO : "realiza"O que você vê
Parse error, terminando em: got 'UNICODE_TEXT'
Por quê
Um token de cardinalidade inválido. Só valem `||`, `o|`, `}|` e `}o` (e seus espelhos); qualquer outra coisa falha. `oo` é o erro de digitação de sempre, por esperar que a notação seja simétrica.
Solução
Use um dos quatro pares. `||--o{` — exatamente um para zero ou mais — cobre a maioria das chaves estrangeiras.
erDiagram
CLIENTE ||--oo{ PEDIDO : "realiza"erDiagram
CLIENTE ||--o{ PEDIDO : "realiza"O que você vê
Parse error, terminando em: Expecting 'ATTRIBUTE_WORD', got 'BLOCK_STOP'
Por quê
Um atributo com nome e sem tipo. Atributos ER são `tipo nome`, e o tipo não é opcional — o que surpreende quem vem de bancos sem esquema.
Solução
Dê um tipo a cada atributo. Invente um se o esquema real não tiver: `string`, `int`, `json`.
erDiagram
CLIENTE {
email
}erDiagram
CLIENTE {
string email
}O que você vê
Parse error, terminando em: Expecting 'NON_IDENTIFYING', 'IDENTIFYING', got 'UNICODE_TEXT'
Por quê
A linha entre as duas marcas de cardinalidade está errada. Ela precisa ter exatamente dois caracteres: `--` para um relacionamento identificador ou `..` para um não identificador. Um hífen só não é uma versão curta de `--`, é erro de sintaxe.
Solução
Use `--` ou `..` entre os pares de cardinalidade.
erDiagram
CLIENTE ||-o{ PEDIDO : "realiza"erDiagram
CLIENTE ||--o{ PEDIDO : "realiza"O que você vê
A cardinalidade desenha, mas descreve a restrição contrária
Por quê
Os dois caracteres mais próximos de cada entidade pertencem àquela entidade, e é facílimo lê-los ao contrário. `CLIENTE ||--o{ PEDIDO` diz que um cliente tem zero ou mais pedidos. Inverta para `CLIENTE }o--|| PEDIDO` e você afirmou que todo cliente pertence a exatamente um pedido, o que não faz sentido — e desenha sem reclamar.
Solução
Leia do centro para fora: as marcas que tocam CLIENTE descrevem quantos clientes, não quantos pedidos.
erDiagram
CLIENTE }o--|| PEDIDO : "realiza"erDiagram
CLIENTE ||--o{ PEDIDO : "realiza"Notas sobre a renderização
Medido no Mermaid 11.12.2 que este site usa.
O layout é ditado pelos relacionamentos, não pelo número de entidades
Uma cadeia de entidades ligadas uma à seguinte desenha como uma coluna alta: quarenta entidades dão um viewBox de aproximadamente 116×7315, contra 116×470 com três. Mas essas mesmas quarenta entidades ligadas a uma única tabela central produzem algo bem mais largo e baixo. É o único tipo de diagrama daqui em que o formato dos seus dados muda o formato do desenho mais que o tamanho dele, então um esquema que não cabe se resolve mais vezes mudando quais relacionamentos você desenha do que quantos.
Em português quase todo rótulo precisa de aspas
Vale insistir porque é a falha silenciosa mais cara desta página. Em inglês os rótulos de relacionamento costumam ter uma palavra só — places, contains, references —, então na documentação inglesa as aspas parecem enfeite. Em português a maioria são locuções com preposição e quebram sem aspas. A regra prática: ponha sempre o rótulo entre aspas e você não precisa mais pensar nisso.
Nomes de entidade diferenciam maiúsculas e por convenção vão em caixa alta
`CLIENTE` e `cliente` são duas entidades distintas, e mencionar as duas no mesmo diagrama dá duas caixas sem aviso. A convenção da caixa alta não é imposta pelo Mermaid, mas vale manter justamente porque deixa evidente qualquer referência em minúsculas escrita por descuido. Acentos funcionam sem problema em nomes de entidade e de coluna; o que convém é decidir de saída se o esquema leva acentos ou não e não misturar.
A gramática é a mais rígida dos seis tipos
Rótulos de relacionamento são obrigatórios, tipos de atributo também, e os tokens de cardinalidade formam um conjunto fechado. Comparado com o Gantt, onde quase tudo desenha e os erros são mudos, o ER falha cedo e em voz alta. Isso é uma virtude: se um diagrama ER desenhou, é bem provável que seja o diagrama que você queria — com a exceção notável dos rótulos sem aspas.
Os rótulos são HTML, então a exportação para PNG redesenha
As tabelas de atributos das entidades são desenhadas dentro de um `<foreignObject>` do SVG, então os navegadores não conseguem rasterizá-las direto num canvas. A exportação para PNG deste site devolvia antes um arquivo SVG em silêncio; agora ela redesenha primeiro com rótulos em texto SVG simples e produz um PNG correto e em tamanho cheio, com tipografia mal perceptivelmente diferente.
Quando usar outro diagrama
Se você precisa de herança, interfaces ou métodos, este é o diagrama errado: o ER não tem nenhum desses conceitos. Use um diagrama de classes e aceite que ele modela o seu código, não as suas tabelas.
Se o esquema é grande, um ER do esquema inteiro vira um painel de parede que ninguém lê. Desenhe as cinco tabelas envolvidas naquilo que você está explicando e deixe o resto de fora; um diagrama é um argumento, não um inventário.
E se a pergunta real é como os dados se movem entre sistemas em vez de como são armazenados, um fluxograma com um subgrafo por sistema responde e um ER não.
Outros tipos de diagrama
Escrito por Dominik Malsch · Última atualização: