database - resueltos - relaciones exclusivas base de datos
¿Cómo se representan las relaciones de supery subtipo en diagramas ER como tablas? (4)
Estoy aprendiendo a interpretar diagramas de relaciones entre entidades en sentencias SQL DDL y estoy confundido por las diferencias en la notación. Considere una relación disjunta como en el siguiente diagrama:
¿Esto se representaría como:
- Tablas de vehículo, 2WD y 4WD (2WD y 4WD apuntarían al PK del vehículo); o
- SOLAMENTE las tablas 2WD y 4WD (y NO la tabla Vehículo), ¿cuáles de las cuales duplicarían los atributos que tendría el Vehículo?
Creo que estas son otras formas de escribir la relación:
Estoy buscando una explicación clara de la diferencia con respecto a las tablas con las que terminarías para cada diagrama.
Notación ER
Hay varias anotaciones ER. No estoy familiarizado con el que está usando, pero está suficientemente claro que está tratando de representar un subtipo (también conocido como herencia, categoría, subclase, jerarquía de generalización ...). Este es el primo relacional de la herencia OOP.
Al realizar la subtipificación, generalmente le preocupan las siguientes decisiones de diseño:
- Resumen versus concreto: ¿se puede crear una instancia del padre? En su ejemplo: ¿puede existir un
Vehicle
sin ser también2WD
o4WD
? 1 - Inclusivo vs. exclusivo: ¿Se puede crear más de un niño para el mismo padre? En su ejemplo, ¿puede el
Vehicle
ser2WD
y4WD
? 2 - Completo vs. incompleto: ¿espera que se agreguen más niños en el futuro? En su ejemplo, ¿espera que una
Bike
o unPlane
(etc ...) pueda agregarse posteriormente al modelo de la base de datos?
La notación de ingeniería de información diferencia entre la relación de subtipo exclusivo y exclusivo. La notación IDEF1X, por otro lado, no reconoce (directamente) esta diferencia, pero diferencia entre el subtipo completo y el incompleto (que IE no).
El siguiente diagrama de ERwin Methods Guide (Capítulo 5, Subtype Relationships) ilustra la diferencia:
Ni IE ni IDEF1X permiten directamente especificar el padre abstracto frente al concreto.
Representación física
Desafortunadamente, las bases de datos prácticas no son compatibles directamente con la herencia, por lo que deberá transformar este diagrama en tablas reales. En general, hay 3 enfoques para hacerlo:
- Coloque todas las clases en la misma tabla y deje los campos secundarios NULL-able. A continuación, puede tener un CHECK para asegurarse de que el subconjunto correcto de los campos no sea NULL.
- Pros: sin JOINing, por lo que algunas consultas pueden beneficiarse. Puede hacer cumplir las claves de nivel parental (por ejemplo, si desea evitar que diferentes vehículos
2WD
y4WD
tengan la misma identificación). Puede hacer cumplir fácilmente a los niños inclusivos frente a los exclusivos y los padres abstractos frente a los concretos (simplemente variando el CHEQUE). - Contras: algunas consultas pueden ser más lentas ya que deben filtrar a los niños "poco interesantes". Dependiendo de su DBMS, las restricciones específicas del niño pueden ser problemáticas. Muchos NULL pueden desperdiciar almacenamiento. Menos adecuado para el subtipado incompleto: agregar un nuevo hijo requiere modificar la tabla existente, lo que puede ser problemático en un entorno de producción.
- Pros: sin JOINing, por lo que algunas consultas pueden beneficiarse. Puede hacer cumplir las claves de nivel parental (por ejemplo, si desea evitar que diferentes vehículos
- Coloque a todos los niños en tablas separadas, pero no tenga una tabla para el padre (en su lugar, repita los campos y restricciones de los padres en todos los niños). Tiene la mayoría de las características de (3) al tiempo que evita JOINs, al precio de menor mantenibilidad (debido a todas estas repeticiones de campo y restricción) y la incapacidad para aplicar claves a nivel parental o representar un padre concreto.
- Coloque a padres e hijos en tablas separadas.
- Pros: limpio. Ningún campo / restricción debe ser repetido artificialmente. Aplica claves a nivel parental y es fácil agregar restricciones específicas del niño. Adecuado para la subtipificación incompleta (es relativamente fácil agregar más tablas secundarias). Ciertas consultas pueden beneficiarse al solo mirar tablas para niños "interesantes".
- Contras: algunas consultas pueden ser UNIDAS-pesadas. Puede ser difícil imponer niños inclusivos frente a niños exclusivos y padres abstractos frente a padres concretos (estos pueden aplicarse declarativamente si el DBMS admite claves externas circulares y diferidas, pero aplicarlas a nivel de aplicación generalmente se considera un mal menor).
Como puede ver, la situación es menos que ideal: tendrá que hacer concesiones sin importar el enfoque que elija. El enfoque (3) probablemente sea su punto de partida, y solo elija una de las alternativas si hay una razón convincente para hacerlo.
1 Supongo que esto es lo que significa el grosor de la línea en sus diagramas.
2 Supongo que esto es lo que significa la presencia o ausencia de "disjuntos" en sus diagramas.
Lo que dijeron otros respondedores, más lo siguiente que va a las claves principales para las tablas de las subclases.
Su caso parece una instancia del patrón de diseño conocido como "Especialización de generalización", o Gen-Spec para abreviar. La pregunta de cómo modelar gen-spec usando tablas de bases de datos aparece todo el tiempo en SO.
Si estuvieras modelando gen-spec en una OOPL como Java, usarías el recurso de herencia de subclase para encargarse de los detalles por ti. Simplemente definiría una clase para ocuparse de los objetos generalizados y luego definiría una colección de subclases, una para cada tipo de objeto especializado. Cada subclase extendería la clase generalizada. Es fácil y directo.
Desafortunadamente, el modelo de datos relacionales no tiene una herencia de subclases integrada, y los sistemas de bases de datos SQL no ofrecen ninguna de esas funciones, que yo sepa. Pero no estás de suerte. Puede diseñar sus tablas para modelar gen-spec de una manera que sea paralela a la estructura de clases de OOP. Luego tiene que organizar su propio mecanismo de herencia cuando se agregan nuevos elementos a la clase generalizada. Los detalles siguen.
La estructura de clases es bastante simple, con una tabla para la clase gen y una tabla para cada subclase de especificaciones. Aquí hay una buena ilustración, del sitio web de Martin Fowler. Herencia de tabla de clase. Tenga en cuenta que en este diagrama, Cricketer es a la vez una subclase y una superclase. Debes elegir qué atributos van en qué tablas. El diagrama muestra un atributo de muestra en cada tabla.
El detalle complicado es cómo se definen las claves principales para estas tablas. La tabla de clase gen obtiene una clave primaria de la forma habitual (a menos que esta tabla sea una especialización de otra generalización, como Cricketers). La mayoría de los diseñadores le dan a la clave principal un nombre estándar, como "Id". Usan la función de autonumeración para rellenar el campo Id. Las tablas de clases de especificaciones obtienen una clave principal, que se puede llamar "Id", pero no se utiliza la función de autonumeración. En cambio, la clave primaria de cada tabla de subclase está restringida para hacer referencia a la clave primaria de la tabla generalizada. Esto hace que cada una de las claves primarias especializadas sea una clave externa así como también una clave principal. Tenga en cuenta que en el caso de los jugadores de críquet, el campo Id hará referencia al campo Id en Players, pero el campo Id en Bowlers hará referencia al campo Id en Cricketers.
Ahora, cuando agrega elementos nuevos, debe mantener la integridad referencial, así es cómo.
Primero inserta una nueva fila en la tabla gen, proporcionando datos para todos sus atributos, excepto la clave principal. El mecanismo de autonumeración genera una clave primaria única. A continuación, inserte una nueva fila en la tabla de especificaciones adecuada, incluidos los datos de todos sus atributos, incluida la clave principal. La clave principal que utiliza es una copia de la nueva clave principal recién generada. Esta propagación de la clave primaria se puede llamar "herencia del pobre".
Ahora, cuando quiere todos los datos generalizados junto con todos los datos especializados de una sola subclase, todo lo que tiene que hacer es unir las dos tablas con las claves comunes. Todos los datos que no pertenecen a la subclase en cuestión se eliminarán de la unión. Es resbaladizo, fácil y rápido.
No siempre hay una sola forma de implementar cualquier modelo de datos en particular. A menudo, hay una transformación que ocurre cuando pasas de un modelo lógico a un modelo físico.
El SQL estándar no tiene una forma clara de aplicar restricciones de subtipo disjuntas .
Si su objetivo es hacer cumplir tantas reglas de su modelo como sea posible usando el esquema, entonces el enfoque estándar para implementar su modelo es usar una tabla para el supertipo y una para cada uno de los subtipos. Esto asegura que solo se usan los atributos aplicables para cada entidad.
Hay un truco de SQL más o menos estándar para aplicar la restricción disjunta. Aparta a algunas personas porque viola las reglas de normalización de una manera sin importancia. Aún así, algunas personas consideran que la técnica es estéticamente ofensiva ya que existe una violación técnica de 2NF.
Esta técnica implica agregar un atributo de partición al supertipo e incluir este atributo de partición en cada subtipo, agregándolo a la clave primaria del subtipo. Junto con las restricciones de verificación que imponen valores específicos para los atributos de partición, esto asegura que cada entidad puede tener como máximo un subtipo. La técnica está documentada en detalle en muchos lugares, como este blog .
Por lo general, cuando realiza una relación Súper tipo / subtipo en el diseño de su base de datos, necesita crear una tabla separada para su tipo de Entidad General (Súper tipo) y tablas separadas para su (s) versión (s) de Entidad Especializada (Subtipo) inconexo o no. En su caso, deberá crear una tabla para VEHÍCULO y una clave principal y algunos atributos que sean comunes o compartidos por todos los subtipos. Luego, deberá crear tablas separadas para 2WD y 4WD junto con atributos específicos solo para esas tablas. Por ejemplo
entonces puede consultar esas tablas mediante el uso de uniones SQL