KEPLIN Docs

Relaciones y enums

Conectar tablas unas con otras — cardinalidad, navegadores, relaciones físicas y virtuales — y cerrar el conjunto de valores de un campo con un enum.

Una tabla sola guarda una lista. Una aplicación necesita más: que los contactos sepan a qué cuenta pertenecen, que las oportunidades sepan de quién son, que un campo estado solo acepte los estados que existen.

Son las dos piezas de esta página: las relaciones, que conectan entidades entre sí, y los enums, que cierran el conjunto de valores posibles de un campo.

Las relaciones

En el diagrama del modelo, cada relación es una línea entre dos entidades, con una etiqueta que dice el nombre del camino y la cardinalidad — en la Gestión de Clientes, conta · 1:N entre Contas y Contactos, y otra igual entre Contas y Oportunidades.

El modelo de la app Gestión de Clientes: las entidades Contas, Contactos y Oportunidades, con las dos relaciones dibujadas entre ellas.
El modelo de la app Gestión de Clientes: las entidades Contas, Contactos y Oportunidades, con las dos relaciones dibujadas entre ellas.

Una relación tiene siempre dos lados:

  • El lado hijo (child), que guarda la referencia — la columna conta_id de la tabla contactos.
  • El lado padre (parent), que es referenciado — la columna id de la tabla contas.

Crear una relación

Las relaciones se dibujan en el diagrama, conectando un campo con otro:

  1. Pasa el ratón sobre el campo del lado hijo — la fila responde con la pista Arrastra a un campo de otra tabla para conectar.
  2. Arrastra desde ese campo hasta el campo del lado padre (típicamente la clave primaria de la otra entidad) y suelta.
  3. Se abre el diálogo Nueva relación, ya con las dos entidades y las dos columnas rellenadas — vinieron del arrastre y no se editan ahí.
  4. Rellena el resto (a continuación) y confirma con Crear relación.

La cardinalidad

El primer campo del diálogo es la Cardinalidad — cuántos de cada lado:

Opción Cuándo se usa
One-to-many (1:N) Una cuenta tiene varios contactos. Es el caso más común.
Many-to-one (N:1) Lo mismo, visto desde el otro lado.
One-to-one (1:1) Un registro para un registro — una cuenta y su ficha fiscal.
Many-to-many (N:N) Muchos a muchos — etiquetas en cuentas, formadores en cursos. Necesita una tabla de unión.

Según la elección, el diálogo muestra Child (tiene la FK) y Parent (referenciada) — o, en el caso N:N, Entidad A y Entidad B.

Los navegadores

Los dos campos siguientes son los navegadores — el corazón de la relación, y lo que la hace útil fuera del diagrama.

Un navegador es un campo virtual que no existe en la base de datos: sirve para saltar de un registro a los registros relacionados y para traer las columnas del otro lado en las APIs. Son ellos los que hacen que una consulta de contactos devuelva, junto con cada contacto, el nombre de la cuenta a la que pertenece — sin segunda consulta y sin código.

  • Navigator en Contactos → Contas — el camino del hijo al padre. Un nombre en singular: conta.
  • Navigator en Contas → [Contactos] — el camino del padre a los hijos. Un nombre en plural: contactos. Los corchetes en el rótulo dicen que este lado devuelve una lista.

Dejar uno de los campos vacío es una decisión legítima: ese lado simplemente no se expone. Si nadie necesita ir de una cuenta a sus contactos, no creas el camino.

En la tarjeta de la entidad, los navegadores aparecen en la sección Navegación, con el nombre a la izquierda y el destino a la derecha — entre corchetes cuando es una lista.

La entidad Contactos con la sección Navegación: el navegador conta lleva al registro de la cuenta a la que el contacto pertenece.
La entidad Contactos con la sección Navegación: el navegador conta lleva al registro de la cuenta a la que el contacto pertenece.

Consejo

Trata los nombres de los navegadores como parte del lenguaje de la app: conta, contactos, linhas, responsavel. Son los que vas a leer en las APIs, en los datastores de las pantallas y en el código de los eventos — y un fk_ct_2 mal elegido hoy es confusión para siempre.

Física o virtual

El campo Tipo de relación decide si la relación también se escribe en la base de datos:

Opción Qué hace
Virtual — solo en el modelo de la plataforma La relación existe para la plataforma: navegadores, APIs, pantallas. La base de datos no se toca.
Física — crea la FK en la base de datos Además del modelo, se crea la clave foránea en el motor: pasa a ser el propio motor el que rechaza un conta_id que no exista.

La relación física es más segura — la integridad deja de depender de quien escribe. La virtual es lo que queda cuando no se puede (o no se quiere) tocar el esquema de la base de datos: bases de datos de terceros, tablas compartidas con otros sistemas, datos históricos que no pasarían la verificación.

Al eliminar el padre

Al eliminar el padre (ON DELETE) dice qué pasa con los hijos cuando el registro padre se elimina:

Opción Qué pasa
Nada (bloquea si hay hijos) La eliminación falla mientras haya hijos.
Restrict — bloquea inmediatamente Lo mismo, verificado al momento.
Cascade — elimina los hijos Eliminar la cuenta elimina sus contactos y sus oportunidades.
Set NULL — suelta los hijos Los hijos se quedan sin padre (la columna pasa a vacía). Exige que la columna acepte vacío.

En una relación física, esta regla la aplica el motor. En una relación virtual, queda guardada en el modelo y pasa a valer si un día la relación se materializa.

Atención

Cascade es cómodo y es irreversible: eliminar una cuenta se lleva contactos, oportunidades y todo lo que cuelgue de ella. En datos de negocio, la costumbre es preferir Nada y tratar la eliminación como un proceso — solo se elimina lo que ya no tiene nada dependiente.

Muchos-a-muchos

Con Many-to-many (N:N) el diálogo pide tres cosas más, porque una relación de estas necesita una tabla en medio (la tabla de unión), con una referencia para cada lado:

Campo Qué es
Tabla de unión La tabla que conecta las dos — por ejemplo conta_etiqueta.
Columna → A (child) La columna de la unión que apunta a la primera entidad.
Columna → B (parent) La columna de la unión que apunta a la segunda.

La tabla de unión tiene que existir antes: créala como cualquier otra (ver Tablas y campos).

Relaciones que ya vienen hechas

Al importar una tabla al modelo, las claves foráneas que ya existan en la base de datos entran solas como relaciones, con navegadores propuestos a partir de los nombres de las tablas. Así es como la Gestión de Clientes nació con sus dos relaciones — solo hace falta confirmar si los nombres de los navegadores son los que quieres leer en el resto de la app.

Quitar una relación

Haz clic en la línea de la relación en el diagrama y confirma. La pregunta es explícita: ¿Quitar esta relación del modelo? — y la respuesta también: la relación sale del modelo de la plataforma y una FK física ya creada en la base de datos NO se elimina. Si querías deshacer de verdad la clave foránea en el motor, eso se hace en la base de datos.

Para qué sirven, después

Hecha la relación, aparece en todas partes:

  • En las APIs, como campos anidados: una consulta de contactos puede devolver conta { nome, cidade }.
  • En los datastores de las pantallas, para montar maestro-detalle — la tabla de contactos filtrada por el id de la cuenta cargada (ver Datastores y datos).
  • En la integridad de los datos, cuando la relación es física.

Los enums

Un enum es un conjunto cerrado de valores para un campo: el estado de una cuenta es Activa, Suspendida o Perdida, y nada más. En vez de dejar que el campo acepte texto libre — y acabar con «activa», «Activa», «ACTIVA» y «activo» en la misma columna — se declara el conjunto una vez.

Crear un enum

El enum nace en la columna, en el momento en que le das el tipo:

  1. En el diálogo Nueva tabla (o en Editar estructura), selecciona la columna.
  2. En Tipo, elige enum.
  3. Aparece la caja Elementos del enum. Haz clic en Añadir elemento para cada valor.
  4. Rellena las tres columnas de cada elemento:
Columna Qué es
Valor El valor guardado. Letras, dígitos y _, empezando por letra — por convención en mayúsculas: ATIVO, EM_ANALISE.
Label El texto que las personas ven: Activo, En análisis.
Color Un color opcional, usado por los widgets que pintan estados (el Kanban, las reglas de formato).

Una columna de tipo enum abre los Elementos del enum — cada elemento con valor, etiqueta y color.
Una columna de tipo enum abre los Elementos del enum — cada elemento con valor, etiqueta y color.

Cada columna enumerada tiene su enum, y su nombre se deriva de la tabla y de la columna — la columna tipo de la tabla actividades da el enum ActividadesTipo.

Nota

En la base de datos, una columna enum se guarda en un campo estructurado — la propia caja avisa: En la BD queda un campo JSON (1 o N valores). Eso es lo que permite que el mismo campo sirva para una elección única hoy y para elección múltiple mañana, sin cambiar el esquema.

Cambiar un enum

Reabre Editar estructura en la tabla, selecciona la columna y toca los Elementos del enum: añadir, cambiar la etiqueta, cambiar el color, quitar con la ×. Confirma con Aplicar cambios.

Cambiar la etiqueta o el color es seguro — son solo presentación. Cambiar o quitar un valor no lo es: los registros que ya tenían el valor antiguo se quedan con un valor que el enum ya no conoce.

El tipo `enum` en la lista de tipos de columna, junto a los tipos normales.
El tipo `enum` en la lista de tipos de columna, junto a los tipos normales.

Dónde aparecen los enums

Un campo enumerado deja de ser texto libre en toda la plataforma:

Dónde Qué cambia
En el diagrama El campo aparece en cursiva, con el nombre del enum en el lugar del tipo.
En las APIs El campo queda con un tipo de valores fijos, y la API rechaza cualquier valor de fuera de la lista.
En el widget Lista En Origen de las opciones, se elige Enum del modelo y luego el Campo enum — las opciones y las etiquetas vienen del modelo, y no hay listas que mantener en dos sitios.
En el Kanban En Fuente de las columnas, la opción Enum crea una columna por valor del enum, ya con los colores.
En las reglas de formato Las condiciones comparan con los valores del enum.

Consejo

Siempre que un campo tiene un conjunto conocido de valores — estado, tipo, prioridad, canal — hazlo un enum en vez de una caja de texto. Ganas las etiquetas traducibles, los colores, los filtros correctos y un Kanban gratis.

¿Por qué no…?

  • ¿Por qué no puedo arrastrar de un campo al otro? El arrastre empieza en la fila del campo del lado hijo y acaba en la fila del campo del lado padre. Si estás arrastrando la tarjeta entera, la estás moviendo en el diagrama — agarra la fila del campo.
  • ¿Por qué la API no devuelve los datos de la tabla relacionada? Falta el navegador de ese lado. Un navegador vacío es un lado que no se expuso a propósito — crea la relación de nuevo con el nombre rellenado.
  • ¿Por qué falló la creación de la relación física? Una clave foránea solo se acepta si los datos ya existentes la respetan. Si hay hijos apuntando a padres que no existen, el motor la rechaza — limpia los huérfanos primero, o crea la relación como virtual.
  • ¿Por qué sigo viendo la relación después de quitarla? La quitaste del modelo; la clave foránea en la base de datos sigue ahí y es ella la que la reimportación vuelve a traer.
  • ¿Por qué mi campo enum muestra el valor en vez de la etiqueta? El widget no está conectado al enum del modelo — en vez de una lista fija, elige Enum del modelo y apunta el Campo enum.