Relations et enums
Relier les tables entre elles — cardinalité, navigators, relations physiques et virtuelles — et fermer l'ensemble des valeurs d'un champ avec un enum.
Une table seule conserve une liste. Une application a besoin de plus : que les contacts sachent à quel compte ils appartiennent, que les opportunités sachent à qui elles sont, qu'un champ état n'accepte que les états qui existent.
Ce sont les deux pièces de cette page : les relations, qui relient les entités les unes aux autres, et les enums, qui ferment l'ensemble des valeurs possibles d'un champ.
Les relations
Dans le diagramme du modèle, chaque relation est une ligne entre deux entités,
avec une étiquette qui donne le nom du chemin et la cardinalité — dans Gestion
des Clients, conta · 1:N entre Contas et Contactos, et une autre
identique entre Contas et Oportunidades.

Une relation a toujours deux côtés :
- Le côté enfant (child), qui conserve la référence — la colonne
conta_idde la tablecontactos. - Le côté parent (parent), qui est référencé — la colonne
idde la tablecontas.
Créer une relation
Les relations se dessinent dans le diagramme, en reliant un champ à un autre :
- Passez la souris sur le champ du côté enfant — la ligne répond par l'aide Glissez vers un champ d'une autre table pour lier.
- Faites glisser depuis ce champ jusqu'au champ du côté parent (typiquement la clé primaire de l'autre entité) et lâchez.
- La boîte de dialogue Nouvelle relation s'ouvre, déjà avec les deux entités et les deux colonnes remplies — elles viennent du glisser-déposer et ne se modifient pas là.
- Remplissez le reste (voir plus bas) et confirmez avec Créer la relation.
La cardinalité
Le premier champ de la boîte de dialogue est la Cardinalité — combien de chaque côté :
| Option | Quand l'utiliser |
|---|---|
| Un-à-plusieurs (1:N) | Un compte a plusieurs contacts. C'est le cas le plus courant. |
| Plusieurs-à-un (N:1) | Le même, vu de l'autre côté. |
| Un-à-un (1:1) | Un enregistrement pour un enregistrement — un compte et sa fiche fiscale. |
| Plusieurs-à-plusieurs (N:N) | Beaucoup vers beaucoup — étiquettes sur des comptes, formateurs sur des cours. Nécessite une table de jonction. |
Selon le choix, la boîte de dialogue affiche Child (porte la FK) et Parent (référencée) — ou, dans le cas N:N, Entité A et Entité B.
Les navigators
Les deux champs suivants sont les navigators — le cœur de la relation, et ce qui la rend utile en dehors du diagramme.
Un navigator est un champ virtuel qui n'existe pas dans la base de données : il sert à sauter d'un enregistrement vers les enregistrements liés et à ramener les colonnes de l'autre côté dans les APIs. Ce sont eux qui font qu'une requête de contacts renvoie, avec chaque contact, le nom du compte auquel il appartient — sans deuxième requête et sans code.
- Navigator sur Contactos → Contas — le chemin de l'enfant vers le parent. Un
nom au singulier :
conta. - Navigator sur Contas → [Contactos] — le chemin du parent vers les enfants.
Un nom au pluriel :
contactos. Les crochets dans le libellé disent que ce côté renvoie une liste.
Laisser l'un des champs vide est une décision légitime : ce côté n'est simplement pas exposé. Si personne n'a besoin d'aller d'un compte vers ses contacts, vous ne créez pas le chemin.
Sur la carte de l'entité, les navigators apparaissent dans la section Navigation, avec le nom à gauche et la destination à droite — entre crochets quand c'est une liste.

Dica
Traitez les noms des navigators comme faisant partie de la langue de l'app :
conta, contactos, linhas, responsavel. Ce sont eux que vous lirez dans
les APIs, dans les datastores des écrans et dans le code des événements — et un
fk_ct_2 mal choisi aujourd'hui, c'est de la confusion pour toujours.
Physique ou virtuelle
Le champ Type de relation décide si la relation est aussi écrite dans la base de données :
| Option | Ce qu'elle fait |
|---|---|
| Virtuelle — uniquement dans le modèle de la plateforme | La relation existe pour la plateforme : navigators, APIs, écrans. La base de données n'est pas touchée. |
| Physique — crée la FK dans la base de données | En plus du modèle, la clé étrangère est créée dans le moteur : c'est désormais le moteur lui-même qui refuse un conta_id qui n'existe pas. |
La relation physique est plus sûre — l'intégrité cesse de dépendre de celui qui écrit. La virtuelle est ce qui reste quand on ne peut pas (ou ne veut pas) toucher au schéma de la base de données : bases de données de tiers, tables partagées avec d'autres systèmes, données historiques qui ne passeraient pas la vérification.
À la suppression du parent
À la suppression du parent (ON DELETE) dit ce qui arrive aux enfants quand l'enregistrement parent est supprimé :
| Option | Ce qui se passe |
|---|---|
| Rien (bloque s'il y a des enfants) | La suppression échoue tant qu'il reste des enfants. |
| Restrict — bloque immédiatement | La même chose, vérifiée tout de suite. |
| Cascade — supprime les enfants | Supprimer le compte supprime ses contacts et ses opportunités. |
| Set NULL — détache les enfants | Les enfants se retrouvent sans parent (la colonne devient vide). Exige que la colonne accepte le vide. |
Dans une relation physique, cette règle est appliquée par le moteur. Dans une relation virtuelle, elle est enregistrée dans le modèle et prend effet si un jour la relation est matérialisée.
Atenção
Cascade est pratique et irréversible : supprimer un compte emporte contacts, opportunités et tout ce qui y est accroché. Sur des données métier, l'usage est de préférer Rien et de traiter la suppression comme un processus — on ne supprime que ce dont plus rien ne dépend.
Plusieurs-à-plusieurs
Avec Plusieurs-à-plusieurs (N:N), la boîte de dialogue demande trois choses de plus, parce qu'une relation de ce genre a besoin d'une table au milieu (la table de jonction), avec une référence pour chaque côté :
| Champ | Ce que c'est |
|---|---|
| Table de jonction | La table qui relie les deux — par exemple conta_etiqueta. |
| Colonne → A (child) | La colonne de la jonction qui pointe vers la première entité. |
| Colonne → B (parent) | La colonne de la jonction qui pointe vers la seconde. |
La table de jonction doit exister avant : créez-la comme n'importe quelle autre (voir Tables et champs).
Les relations qui arrivent toutes faites
À l'import d'une table dans le modèle, les clés étrangères qui existent déjà dans la base de données entrent toutes seules comme relations, avec des navigators proposés à partir des noms des tables. C'est ainsi que Gestion des Clients est née avec ses deux relations — il suffit de vérifier si les noms des navigators sont ceux que vous voulez lire dans le reste de l'app.
Retirer une relation
Cliquez sur la ligne de la relation dans le diagramme et confirmez. La question est explicite : Retirer cette relation du modèle ? — et la réponse aussi : la relation sort du modèle de la plateforme et une FK physique déjà créée dans la base de données N'EST PAS retirée. Si vous vouliez vraiment défaire la clé étrangère dans le moteur, cela se fait dans la base de données.
À quoi elles servent, ensuite
Une fois la relation faite, elle apparaît partout :
- Dans les APIs, sous forme de champs imbriqués : une requête de contacts
peut renvoyer
conta { nome, cidade }. - Dans les datastores des écrans, pour monter un maître-détail — la table de
contacts filtrée par l'
iddu compte chargé (voir Datastores et données). - Dans l'intégrité des données, quand la relation est physique.
Les enums
Un enum est un ensemble fermé de valeurs pour un champ : l'estado d'un
compte est Active, Suspendue ou Perdue, et rien d'autre. Au lieu de laisser
le champ accepter du texte libre — et de finir avec « active », « Active »,
« ACTIVE » et « actif » dans la même colonne — on déclare l'ensemble une fois.
Créer un enum
L'enum naît sur la colonne, au moment où vous lui donnez son type :
- Dans la boîte de dialogue Nouvelle table (ou dans Modifier la structure), sélectionnez la colonne.
- Dans Type, choisissez
enum. - Le cadre Éléments de l'enum apparaît. Cliquez sur Ajouter un élément pour chaque valeur.
- Remplissez les trois colonnes de chaque élément :
| Colonne | Ce que c'est |
|---|---|
| Valeur | La valeur enregistrée. Lettres, chiffres et _, commençant par une lettre — par convention en majuscules : ATIVO, EM_ANALISE. |
| Libellé | Le texte que les gens voient : Actif, En analyse. |
| Couleur | Une couleur facultative, utilisée par les widgets qui peignent des états (le Kanban, les règles de formatage). |

Chaque colonne énumérée a son enum, et son nom dérive de la table et de la
colonne — la colonne tipo de la table actividades donne l'enum
ActividadesTipo.
Nota
Dans la base de données, une colonne enum est conservée dans un champ structuré — le cadre lui-même le signale : Dans la BD, c'est un champ JSON (1 ou N valeurs). C'est cela qui permet au même champ de servir pour un choix unique aujourd'hui et pour un choix multiple demain, sans changer le schéma.
Modifier un enum
Rouvrez Modifier la structure sur la table, sélectionnez la colonne et touchez aux Éléments de l'enum : ajouter, changer le libellé, changer la couleur, retirer avec le ×. Confirmez avec Appliquer les modifications.
Changer le libellé ou la couleur est sans risque — ce n'est que de la présentation. Changer ou retirer une valeur ne l'est pas : les enregistrements qui portaient déjà l'ancienne valeur se retrouvent avec une valeur que l'enum ne connaît plus.

Où les enums apparaissent
Un champ énuméré cesse d'être du texte libre dans toute la plateforme :
| Où | Ce qui change |
|---|---|
| Dans le diagramme | Le champ apparaît en italique, avec le nom de l'enum à la place du type. |
| Dans les APIs | Le champ prend un type à valeurs fixes, et l'API refuse toute valeur hors de la liste. |
| Dans le widget Liste | Dans Source des options, on choisit Enum du modèle puis le Champ enum — les options et les libellés viennent du modèle, et il n'y a pas de listes à tenir à jour à deux endroits. |
| Dans le Kanban | Dans Source des colonnes, l'option Enum crée une colonne par valeur de l'enum, avec les couleurs. |
| Dans les règles de formatage | Les conditions comparent avec les valeurs de l'enum. |
Dica
Chaque fois qu'un champ a un ensemble connu de valeurs — état, type, priorité, canal — faites-en un enum plutôt qu'un champ de texte. Vous gagnez les libellés traduisibles, les couleurs, les bons filtres et un Kanban gratuit.
Pourquoi ne… ?
- Pourquoi n'arrivé-je pas à glisser d'un champ vers l'autre ? Le glisser-déposer commence sur la ligne du champ du côté enfant et se termine sur la ligne du champ du côté parent. Si vous faites glisser la carte entière, vous la déplacez dans le diagramme — attrapez la ligne du champ.
- Pourquoi l'API ne renvoie-t-elle pas les données de la table liée ? Il manque le navigator de ce côté. Un navigator vide est un côté qui n'a pas été exposé, exprès — recréez la relation avec le nom rempli.
- Pourquoi la création de la relation physique a-t-elle échoué ? Une clé étrangère n'est acceptée que si les données déjà présentes la respectent. S'il y a des enfants qui pointent vers des parents qui n'existent pas, le moteur refuse — nettoyez d'abord les orphelins, ou créez la relation en virtuelle.
- Pourquoi est-ce que je vois toujours la relation après l'avoir retirée ? Vous l'avez retirée du modèle ; la clé étrangère dans la base de données est toujours là et c'est elle que la réimportation ramène.
- Pourquoi mon champ enum affiche-t-il la valeur au lieu du libellé ? Le widget n'est pas relié à l'enum du modèle — au lieu d'une liste fixe, choisissez Enum du modèle et pointez le Champ enum.