KEPLIN Docs

Relações e enums

Ligar tabelas umas às outras — cardinalidade, navegadores, relações físicas e virtuais — e fechar o conjunto de valores de um campo com um enum.

Uma tabela sozinha guarda uma lista. Uma aplicação precisa de mais: que os contactos saibam a que conta pertencem, que as oportunidades saibam de quem são, que um campo estado só aceite os estados que existem.

São as duas peças desta página: as relações, que ligam entidades umas às outras, e os enums, que fecham o conjunto de valores possíveis de um campo.

As relações

No diagrama do modelo, cada relação é uma linha entre duas entidades, com uma etiqueta que diz o nome do caminho e a cardinalidade — na Gestão de Clientes, conta · 1:N entre Contas e Contactos, e outra igual entre Contas e Oportunidades.

O modelo da app Gestão de Clientes: as entidades Contas, Contactos e Oportunidades, com as duas relações desenhadas entre elas.
O modelo da app Gestão de Clientes: as entidades Contas, Contactos e Oportunidades, com as duas relações desenhadas entre elas.

Uma relação tem sempre dois lados:

  • O lado filho (child), que guarda a referência — a coluna conta_id da tabela contactos.
  • O lado pai (parent), que é referenciado — a coluna id da tabela contas.

Criar uma relação

As relações desenham-se no diagrama, ligando um campo a outro:

  1. Passa o rato sobre o campo do lado filho — a linha responde com a dica Arrasta para um campo de outra tabela para ligar.
  2. Arrasta desse campo até ao campo do lado pai (tipicamente a chave primária da outra entidade) e larga.
  3. Abre-se o diálogo Nova relação, já com as duas entidades e as duas colunas preenchidas — vieram do arrasto e não se editam ali.
  4. Preenche o resto (a seguir) e confirma com Criar relação.

A cardinalidade

O primeiro campo do diálogo é a Cardinalidade — quantos de cada lado:

Opção Quando se usa
One-to-many (1:N) Uma conta tem vários contactos. É o caso mais comum.
Many-to-one (N:1) O mesmo, visto do outro lado.
One-to-one (1:1) Um registo para um registo — uma conta e a sua ficha fiscal.
Many-to-many (N:N) Muitos para muitos — etiquetas em contas, formadores em cursos. Precisa de uma tabela de junção.

Conforme a escolha, o diálogo mostra Child (tem a FK) e Parent (referenciada) — ou, no caso N:N, Entidade A e Entidade B.

Os navegadores

Os dois campos seguintes são os navegadores — o coração da relação, e o que a torna útil fora do diagrama.

Um navegador é um campo virtual que não existe na base de dados: serve para saltar de um registo para os registos relacionados e para trazer as colunas do outro lado nas APIs. São eles que fazem uma consulta de contactos devolver, junto com cada contacto, o nome da conta a que pertence — sem segunda consulta e sem código.

  • Navigator em Contactos → Contas — o caminho do filho para o pai. Um nome no singular: conta.
  • Navigator em Contas → [Contactos] — o caminho do pai para os filhos. Um nome no plural: contactos. Os parêntesis rectos no rótulo dizem que este lado devolve uma lista.

Deixar um dos campos vazio é uma decisão legítima: esse lado simplesmente não é exposto. Se ninguém precisa de ir de uma conta para os seus contactos, não crias o caminho.

No cartão da entidade, os navegadores aparecem na secção Navegação, com o nome à esquerda e o destino à direita — entre parêntesis rectos quando é uma lista.

A entidade Contactos com a secção Navegação: o navegador conta leva ao registo da conta a que o contacto pertence.
A entidade Contactos com a secção Navegação: o navegador conta leva ao registo da conta a que o contacto pertence.

Dica

Trata os nomes dos navegadores como parte da linguagem da app: conta, contactos, linhas, responsavel. São eles que vais ler nas APIs, nos datastores dos ecrãs e no código dos eventos — e um fk_ct_2 mal escolhido hoje é confusão para sempre.

Física ou virtual

O campo Tipo de relação decide se a relação também é escrita na base de dados:

Opção O que faz
Virtual — só no modelo da plataforma A relação existe para a plataforma: navegadores, APIs, ecrãs. A base de dados não é tocada.
Física — cria a FK na base de dados Além do modelo, é criada a chave estrangeira no motor: passa a ser o próprio motor a recusar um conta_id que não exista.

A relação física é mais segura — a integridade deixa de depender de quem escreve. A virtual é o que sobra quando não se pode (ou não se quer) mexer no esquema da base de dados: bases de dados de terceiros, tabelas partilhadas com outros sistemas, dados históricos que não passariam na verificação.

Ao apagar o pai

Ao apagar o pai (ON DELETE) diz o que acontece aos filhos quando o registo pai é apagado:

Opção O que acontece
Nada (bloqueia se houver filhos) A eliminação falha enquanto houver filhos.
Restrict — bloqueia imediatamente O mesmo, verificado logo.
Cascade — apaga os filhos Apagar a conta apaga os contactos e as oportunidades dela.
Set NULL — solta os filhos Os filhos ficam sem pai (a coluna passa a vazia). Exige que a coluna aceite vazio.

Numa relação física, esta regra é aplicada pelo motor. Numa relação virtual, fica guardada no modelo e passa a valer se um dia a relação for materializada.

Atenção

Cascade é conveniente e é irreversível: apagar uma conta leva contactos, oportunidades e tudo o que estiver pendurado. Em dados de negócio, o costume é preferir Nada e tratar a eliminação como um processo — só apaga quem já não tem nada dependente.

Muitos-para-muitos

Com Many-to-many (N:N) o diálogo pede mais três coisas, porque uma relação destas precisa de uma tabela pelo meio (a tabela de junção), com uma referência para cada lado:

Campo O que é
Tabela de junção A tabela que liga as duas — por exemplo conta_etiqueta.
Coluna → A (child) A coluna da junção que aponta para a primeira entidade.
Coluna → B (parent) A coluna da junção que aponta para a segunda.

A tabela de junção tem de existir antes: cria-a como qualquer outra (ver Tabelas e campos).

Relações que já vêm feitas

Ao importar uma tabela para o modelo, as chaves estrangeiras que já existirem na base de dados entram sozinhas como relações, com navegadores propostos a partir dos nomes das tabelas. Foi assim que a Gestão de Clientes nasceu com as suas duas relações — só é preciso confirmar se os nomes dos navegadores são os que queres ler no resto da app.

Remover uma relação

Clica na linha da relação no diagrama e confirma. A pergunta é explícita: Remover esta relação do modelo? — e a resposta também: a relação sai do modelo da plataforma e uma FK física já criada na base de dados NÃO é removida. Se querias mesmo desfazer a chave estrangeira no motor, isso faz-se na base de dados.

Para que servem, depois

Feita a relação, ela aparece em todo o lado:

  • Nas APIs, como campos aninhados: uma consulta de contactos pode devolver conta { nome, cidade }.
  • Nos datastores dos ecrãs, para montar mestre-detalhe — a tabela de contactos filtrada pelo id da conta carregada (ver Datastores e dados).
  • Na integridade dos dados, quando a relação é física.

Os enums

Um enum é um conjunto fechado de valores para um campo: o estado de uma conta é Activa, Suspensa ou Perdida, e mais nada. Em vez de deixar o campo aceitar texto livre — e acabar com "activa", "Activa", "ACTIVA" e "activo" na mesma coluna — declara-se o conjunto uma vez.

Criar um enum

O enum nasce na coluna, no momento em que lhe dás o tipo:

  1. No diálogo Nova tabela (ou em Editar estrutura), selecciona a coluna.
  2. Em Tipo, escolhe enum.
  3. Aparece a caixa Itens do enum. Clica em Adicionar item para cada valor.
  4. Preenche as três colunas de cada item:
Coluna O que é
Valor O valor guardado. Letras, dígitos e _, a começar por letra — por convenção em maiúsculas: ATIVO, EM_ANALISE.
Label O texto que as pessoas vêem: Activo, Em análise.
Cor Uma cor opcional, usada pelos widgets que pintam estados (o Kanban, as regras de formatação).

Uma coluna do tipo enum abre os Itens do enum — cada item com valor, etiqueta e cor.
Uma coluna do tipo enum abre os Itens do enum — cada item com valor, etiqueta e cor.

Cada coluna enumerada tem o seu enum, e o nome dele é derivado da tabela e da coluna — a coluna tipo da tabela actividades dá o enum ActividadesTipo.

Nota

Na base de dados, uma coluna enum é guardada num campo estruturado — a própria caixa avisa: Na BD fica um campo JSON (1 ou N valores). É isso que deixa o mesmo campo servir para uma escolha única hoje e para múltipla escolha amanhã, sem mudar o esquema.

Alterar um enum

Reabre Editar estrutura na tabela, selecciona a coluna e mexe nos Itens do enum: acrescentar, mudar a etiqueta, mudar a cor, remover com o ×. Confirma com Aplicar alterações.

Mudar a etiqueta ou a cor é seguro — são só apresentação. Mudar ou remover um valor não é: os registos que já tinham o valor antigo ficam com um valor que o enum já não conhece.

O tipo `enum` na lista de tipos de coluna, ao lado dos tipos normais.
O tipo `enum` na lista de tipos de coluna, ao lado dos tipos normais.

Onde os enums aparecem

Um campo enumerado deixa de ser texto livre em toda a plataforma:

Onde O que muda
No diagrama O campo aparece em itálico, com o nome do enum no lugar do tipo.
Nas APIs O campo fica com um tipo de valores fixos, e a API recusa qualquer valor de fora da lista.
No widget Lista Em Origem das opções, escolhe-se Enum do modelo e depois o Campo enum — as opções e as etiquetas vêm do modelo, e não há listas para manter em dois sítios.
No Kanban Em Fonte das colunas, a opção Enum cria uma coluna por valor do enum, já com as cores.
Nas regras de formatação As condições comparam com os valores do enum.

Dica

Sempre que um campo tem um conjunto conhecido de valores — estado, tipo, prioridade, canal — faz dele um enum em vez de uma caixa de texto. Ganhas as etiquetas traduzíveis, as cores, os filtros certos e um Kanban de graça.

Porque não…?

  • Porque não consigo arrastar de um campo para o outro? O arrasto começa na linha do campo do lado filho e acaba na linha do campo do lado pai. Se estás a arrastar o cartão inteiro, estás a movê-lo no diagrama — pega na linha do campo.
  • Porque é que a API não devolve os dados da tabela relacionada? Falta o navegador desse lado. Um navegador vazio é um lado que não foi exposto de propósito — cria a relação de novo com o nome preenchido.
  • Porque falhou a criação da relação física? Uma chave estrangeira só é aceite se os dados já existentes a respeitarem. Se houver filhos a apontar para pais que não existem, o motor recusa — limpa os órfãos primeiro, ou cria a relação como virtual.
  • Porque continuo a ver a relação depois de a remover? Removeste-a do modelo; a chave estrangeira na base de dados continua lá e é ela que a reimportação volta a trazer.
  • Porque é que o meu campo enum mostra o valor em vez da etiqueta? O widget não está ligado ao enum do modelo — em vez de uma lista fixa, escolhe Enum do modelo e aponta o Campo enum.