Generalización y especialización (herencia): cuándo usarla
La generalización/especialización modela un conjunto de entidades que comparten atributos comunes (supertipo) y, a la vez, tienen atributos o reglas específicas (subtipos). En bases de datos relacionales no existe “herencia” nativa, así que se implementa con estrategias de mapeo.
Decisiones clave antes de mapear
- Disyunta vs. solapada: ¿una instancia puede pertenecer a más de un subtipo a la vez?
- Total vs. parcial: ¿toda instancia del supertipo debe pertenecer a algún subtipo?
- Estabilidad: ¿los subtipos cambian con frecuencia (nuevas variantes) o son estables?
- Consultas dominantes: ¿se consulta más el supertipo (vista unificada) o cada subtipo por separado?
Ejemplo conceptual: Persona como supertipo y subtipos Cliente y Empleado. Si una persona puede ser ambas cosas, el modelo es solapado; si toda persona debe ser cliente o empleado, es total.
Estrategias de mapeo relacional para herencia
1) Tabla por jerarquía (Single Table Inheritance)
Se usa una sola tabla para el supertipo y todos los subtipos, con una columna discriminadora (por ejemplo, tipo) y columnas opcionales para atributos específicos.
PERSONA( id PK, tipo, nombre, email, ... , salario, fecha_contratacion, limite_credito )- Ventajas: consultas simples (no requiere joins), inserciones rápidas, ideal cuando se consulta “todo junto”.
- Desventajas: muchas columnas nulas, validaciones complejas (asegurar que
salariosolo aplique a empleados), riesgo de “tabla monstruo”. - Cuándo elegirla: pocos subtipos, pocos atributos específicos, alta necesidad de lectura unificada, y tolerancia a nulos.
2) Tabla por subtipo (Class Table Inheritance)
Una tabla para el supertipo con atributos comunes y una tabla por subtipo con atributos específicos. La PK del subtipo también es FK al supertipo (relación 1 a 1).
PERSONA( id PK, nombre, email, ... )
EMPLEADO( id PK/FK -> PERSONA.id, salario, fecha_contratacion )
CLIENTE( id PK/FK -> PERSONA.id, limite_credito )- Ventajas: modelo limpio, sin nulos innecesarios, reglas por subtipo más fáciles, extensible.
- Desventajas: más joins para obtener la vista completa, inserciones requieren varias operaciones, cuidado con integridad (totalidad/disyunción).
- Cuándo elegirla: atributos específicos relevantes, necesidad de integridad fuerte por subtipo, crecimiento moderado de subtipos.
3) Tabla por clase concreta (Concrete Table Inheritance)
No hay tabla del supertipo; cada subtipo tiene su propia tabla con atributos comunes duplicados.
- Escuche el audio con la pantalla apagada.
- Obtenga un certificado al finalizar.
- ¡Más de 5000 cursos para que explores!
Descargar la aplicación
EMPLEADO( id PK, nombre, email, salario, fecha_contratacion )
CLIENTE( id PK, nombre, email, limite_credito )- Ventajas: consultas por subtipo sin joins, tablas autónomas.
- Desventajas: duplicación de columnas, difícil garantizar unicidad global (por ejemplo, email único entre empleados y clientes), reportes unificados requieren
UNION, mantenimiento más costoso. - Cuándo elegirla: subtipos casi nunca se consultan juntos, reglas y ciclos de vida muy distintos, o cuando se prioriza independencia por subtipo.
Criterios prácticos de elección (checklist)
| Criterio | Tabla por jerarquía | Tabla por subtipo | Tabla por clase concreta |
|---|---|---|---|
| Consultas unificadas frecuentes | Alta | Media | Baja |
| Integridad por subtipo (atributos obligatorios) | Baja/Media | Alta | Alta (por tabla) |
| Nulos/columnas opcionales | Muchos | Pocos | Ninguno (pero duplicación) |
| Facilidad de evolución (agregar subtipo) | Media (alter table) | Alta | Media (nueva tabla + reportes) |
| Riesgo de duplicación | Bajo | Bajo | Alto |
Guía paso a paso para decidir
- Lista atributos comunes y atributos exclusivos por subtipo.
- Define reglas: disyunción/solapamiento y totalidad/parcialidad.
- Revisa consultas: ¿necesitas listar “todas las personas” con frecuencia?
- Evalúa integridad: ¿es crítico que ciertos campos sean obligatorios solo en un subtipo?
- Prototipa 2 opciones y estima: número de joins, nulos, y complejidad de constraints.
- Elige la que minimice complejidad total (modelo + consultas + validaciones).
Roles múltiples: cuando una entidad “actúa como” varias cosas
Un error común es crear subtipos para roles que en realidad son contextuales. Por ejemplo, una misma Persona puede ser Comprador en una orden y Solicitante en un ticket. Eso no siempre justifica subtipos permanentes.
Patrón recomendado: roles como relaciones
Modela el rol en la relación o en una tabla intermedia con un atributo rol.
PARTICIPACION( id PK, persona_id FK, proceso_id FK, rol, desde, hasta )- Ventaja: una persona puede tener múltiples roles simultáneos sin forzar herencia.
- Cuándo usarlo: roles dependen del contexto (proceso, documento, proyecto) y pueden cambiar con el tiempo.
Cuándo sí usar subtipos para roles
- Cuando el rol implica atributos propios persistentes (p. ej.,
Empleadoconsalario). - Cuando el rol tiene reglas de negocio estructurales (p. ej., solo empleados pueden aprobar gastos).
Relaciones recursivas: empleado–supervisor y restricciones típicas
Una relación recursiva conecta una entidad consigo misma. El caso clásico es Empleado que supervisa a otros empleados.
Implementación típica
EMPLEADO( id PK, nombre, supervisor_id FK -> EMPLEADO.id NULL )- Cardinalidad usual: un empleado tiene 0..1 supervisor; un supervisor tiene 0..N subordinados.
- Raíz: el director general puede tener
supervisor_idnulo.
Restricciones importantes (y cómo abordarlas)
- Evitar ciclos (A supervisa a B y B supervisa a A, o ciclos largos). En SQL estándar no es trivial con constraints; suele resolverse con lógica en aplicación, procedimientos, o validación con consultas recursivas antes de actualizar.
- Profundidad máxima (opcional): si la organización limita niveles, se valida con reglas adicionales.
- Supervisor debe existir: FK lo asegura; si se permite “supervisor externo”, se modela con otra entidad o un tipo de supervisor.
Si necesitas almacenar jerarquías complejas con consultas frecuentes (por ejemplo, “todos los descendientes”), considera patrones de jerarquías como closure table o materialized path. Úsalos solo si el caso de uso lo exige, porque incrementan complejidad y mantenimiento.
Patrones comunes de diseño de datos
Catálogos y enumeraciones
Los catálogos representan listas controladas (p. ej., tipos de documento, países, estados de una orden). Hay dos enfoques principales:
- Enumeración en código/DB: valores fijos y pocos cambios (p. ej.,
tipo_documento= DNI, PASAPORTE). En DB puede serCHECKo tipo enumerado si el motor lo soporta. - Tabla catálogo: valores administrables (altas/bajas), con metadatos (orden, descripción, vigencia).
CAT_ESTADO_ORDEN( id PK, codigo UNIQUE, nombre, activo )
ORDEN( id PK, estado_id FK -> CAT_ESTADO_ORDEN.id, ... )Criterio: si el negocio necesita administrar la lista sin despliegues, usa tabla catálogo; si es estrictamente fijo y pequeño, una enumeración puede ser suficiente.
Auditoría: created_at, updated_at, y “quién”
Un patrón mínimo de auditoría agrega marcas de tiempo y, si aplica, usuario responsable.
... , created_at, created_by, updated_at, updated_by- Buenas prácticas:
created_atinmutable;updated_atcambia en cada modificación. - Implementación: defaults y triggers pueden ayudar, pero define una convención consistente para todo el esquema.
Historial y vigencia: SCD Tipo 2 (Slowly Changing Dimension)
SCD Tipo 2 guarda el historial de cambios creando nuevas filas con rangos de vigencia. Es útil cuando necesitas responder “¿qué valor tenía este atributo en una fecha pasada?”
Estructura típica
CLIENTE_SCD2( sk PK, cliente_id, nombre, segmento, ...,
valid_from, valid_to, is_current )- cliente_id: identificador de negocio (natural o surrogate estable).
- sk: clave surrogate de versión (cada cambio crea una nueva).
- valid_to: puede ser NULL o una fecha “alta” para la versión actual.
Guía paso a paso para aplicar SCD2
- Identifica atributos historizables (p. ej., segmento, dirección comercial) y separa los no historizables.
- Define la clave de negocio (
cliente_id) y la clave de versión (sk). - Diseña vigencia:
valid_from,valid_to,is_current. - Regla de actualización: al cambiar un atributo historizable, cierra la versión actual (
valid_to= fecha_cambio,is_current= false) e inserta una nueva versión convalid_from= fecha_cambio. - Evita solapamientos: asegura que por
cliente_idexista solo una filais_current= true y que los rangos no se crucen.
Este patrón es potente, pero incrementa volumen y complejidad de consultas; úsalo cuando el historial sea un requisito real, no “por si acaso”.
Manejo de estados: máquinas de estado y trazabilidad
Muchas entidades pasan por estados (p. ej., orden: borrador → confirmada → enviada → entregada → cancelada). Hay dos niveles:
- Estado actual: una FK a catálogo de estados o un valor enumerado.
- Historial de estados: tabla de eventos para auditoría y análisis.
ORDEN( id PK, estado_id FK, ... )
ORDEN_ESTADO_HIST( id PK, orden_id FK, estado_id FK, changed_at, changed_by, motivo )Recomendación: si necesitas saber “cuándo pasó a enviado” o “quién canceló”, crea historial. Si solo importa el estado actual, evita la tabla extra.
Riesgos frecuentes y cómo mantener el modelo comprensible
Riesgo 1: explosión de tablas por subtipos
- Síntoma: docenas de subtipos con 1–2 atributos cada uno, y consultas llenas de joins.
- Mitigación: valida si son roles contextuales (mejor como relación con
rol), o si son “variantes” que encajan mejor en un catálogo + atributos parametrizados (con cuidado). - Regla práctica: si el subtipo no aporta reglas/atributos sustanciales y estables, probablemente no es subtipo.
Riesgo 2: sobreuso de tabla por jerarquía
- Síntoma: una tabla enorme con muchas columnas nulas y validaciones difíciles.
- Mitigación: migra a tabla por subtipo cuando la integridad por subtipo sea importante o cuando la tabla crezca sin control.
Riesgo 3: jerarquías recursivas sin control de ciclos
- Síntoma: datos inconsistentes (ciclos) que rompen reportes y recorridos.
- Mitigación: define una política de validación (en capa de servicio, triggers, o procedimientos) y pruebas automatizadas con consultas recursivas para detectar ciclos.
Riesgo 4: catálogos “cajón de sastre”
- Síntoma: una sola tabla de catálogos genérica para todo, sin integridad semántica.
- Mitigación: prefiere catálogos específicos por dominio (p. ej.,
CAT_ESTADO_ORDEN,CAT_TIPO_PAGO) o, si usas un catálogo genérico, asegúrate de tener claves compuestas y restricciones claras por “familia”.
Riesgo 5: historial (SCD2) aplicado indiscriminadamente
- Síntoma: crecimiento acelerado, consultas complejas, confusión entre “actual” e “histórico”.
- Mitigación: historiza solo atributos con valor analítico/legal; documenta cómo consultar la versión vigente (por
is_currento por rango de fechas).
Prácticas para mantener el modelo entendible
- Nombres consistentes: sufijos como
_HIST,_SCD2,CAT_ayudan a leer el esquema. - Documenta reglas de herencia: disyunta/solapada y total/parcial, y cómo se implementa (constraints, lógica).
- Vistas de consumo: crea vistas que presenten una “cara simple” (por ejemplo, una vista unificada de persona) cuando el modelo físico sea más complejo.
- Diagrama por contexto: separa el diagrama en áreas (personas, órdenes, auditoría) para evitar un “mapa imposible”.