Tengo que modelar una situación en la que tengo una tabla Chequing_Account (que contiene el presupuesto, el número iban y otros detalles de la cuenta) que tiene que estar relacionada con dos tablas diferentes Persona y Corporación, que pueden tener 0, 1 o muchas cuentas de cheques.
En otras palabras, tengo dos relaciones de 1 a muchos con la misma tabla Chequing account
Me gustaría escuchar soluciones para este problema que respeten los requisitos de normalización. La mayoría de las soluciones que he escuchado son:
1) encontrar una entidad común a la que pertenezcan Persona y Corporación y crear una tabla de enlaces entre esta y la tabla Chequing_Account, esto no es posible en mi caso e incluso si lo fuera, quiero resolver el problema general y no esta instancia específica.
2) Cree dos tablas de enlaces PersonToChequingAccount y CorporationToChequingAccount que relacionen las dos entidades con las cuentas de cheques. Sin embargo, no quiero que dos Personas tengan la misma cuenta de cheques, ¡y no quiero que una persona física y una Corporación compartan una cuenta de cheques! ver esta imagen
3) Crear dos claves foráneas en Chequing Account que apunten a Corporación y Persona física, sin embargo, exigiría que una Persona y una Compañía puedan tener muchas cuentas de cheques, sin embargo, tendría que asegurarme manualmente de que para cada fila de ChequingAccount no ambas relaciones apuntan a Corporación y persona física porque una cuenta de cheques es de una corporación o de una persona física. ver esta imagen
¿Hay alguna otra solución más limpia para este problema?
fuente
OwnerTypeID
en laChecquingAccount
mesa, con1=Corporation
y2=NaturalPerson
? De esa manera solo necesita unoOwnerID
en laChecquingAccount
tabla, que puede indexar junto conOwnerTypeID
.CHECK (CorporationID IS NOT NULL AND NaturalPersonID IS NULL OR CorporationID IS NULL AND NaturalPersonID IS NOT NULL)
aunque prefiero la solución 1 (pero esa soy yo). Es mucho más "limpio".ChecquingAccount
tabla un registro deOwnerTypeID=1
eOwnerID=123
, indicando que es un tipoCorporation
, por lo tanto, ID123
en laCorporation
tabla. El OwnerTypeID le dice qué tabla, y el OwnerID le dice la ID en esa tabla.Customers
mesa.Respuestas:
Las bases de datos relacionales no están construidas para manejar esta situación perfectamente. Debe decidir qué es lo más importante para usted y luego hacer sus compensaciones. Tienes varios objetivos:
El problema es que algunos de estos objetivos compiten entre sí.
Solución de subtipificación
Puede elegir una solución de subtipificación en la que cree un supertipo que incorpore corporaciones y personas. Este supertipo probablemente tendría una clave compuesta de la clave natural del subtipo más un atributo de partición (por ejemplo
customer_type
). Esto está bien en lo que respecta a la normalización y le permite hacer cumplir la integridad referencial, así como la restricción de que las corporaciones y las personas se excluyan mutuamente. El problema es que esto hace que la recuperación de datos sea más difícil, porque siempre tiene que bifurcarsecustomer_type
cuando se une la cuenta al titular de la cuenta. Esto probablemente significa usarUNION
y tener muchos SQL repetitivos en su consulta.Solución de dos claves extranjeras
Puede elegir una solución en la que mantenga dos claves extranjeras en la tabla de su cuenta, una para la corporación y otra para la persona. Esta solución también le permite mantener integridad referencial, normalización y exclusividad mutua. También tiene el mismo inconveniente de recuperación de datos que la solución de subtipado. De hecho, esta solución es igual que la solución de subtipado, excepto que llega al problema de bifurcar su lógica de unión "antes".
Sin embargo, muchos modeladores de datos considerarían esta solución inferior a la solución de subtipado debido a la forma en que se aplica la restricción de exclusividad mutua. En la solución de subtipado, utiliza claves para imponer la exclusividad mutua. En las dos soluciones de clave externa, utiliza una
CHECK
restricción. Conozco algunas personas que tienen un sesgo injustificado contra las restricciones de verificación. Estas personas preferirían la solución que mantiene las restricciones en las claves.Solución de atributos de particionamiento "desnormalizados"
Hay otra opción en la que mantiene una sola columna de clave externa en la tabla de la cuenta de cheques y usa otra columna para indicarle cómo interpretar la columna de clave externa (RoKa's
OwnerTypeID
columna). Esto esencialmente elimina la tabla de supertipo en la solución de subtipado al desnormalizar el atributo de partición en la tabla secundaria. (Tenga en cuenta que esto no es estrictamente "desnormalización" según la definición formal, porque el atributo de partición es parte de una clave primaria). Esta solución parece bastante simple ya que evita tener una tabla adicional para hacer más o menos lo mismo y reduce el número de columnas de clave externa a uno. El problema con esta solución es que no evita la ramificación de la lógica de recuperación y, además, no le permite mantener la integridad referencial declarativa . Las bases de datos SQL no tienen la capacidad de administrar una sola columna de clave externa para una de varias tablas principales.Solución de dominio de clave primaria compartida
Una forma en que las personas a veces se ocupan de este problema es usar un solo grupo de ID para que no haya confusión para una ID dada si pertenece a un subtipo u otro. Esto probablemente funcionaría de manera bastante natural en un escenario bancario, ya que no va a emitir el mismo número de cuenta bancaria tanto para una corporación como para una persona física. Esto tiene la ventaja de evitar la necesidad de un atributo de partición. Puede hacer esto con o sin una tabla de supertipo. El uso de una tabla de supertipo le permite usar restricciones declarativas para imponer la unicidad. De lo contrario, esto debería hacerse cumplir procesalmente. Esta solución está normalizada, pero no le permitirá mantener la integridad referencial declarativa a menos que mantenga la tabla de supertipo. Todavía no hace nada para evitar una lógica de recuperación compleja.
Por lo tanto, puede ver que no es realmente posible tener un diseño limpio que siga todas las reglas, al mismo tiempo que simplifica la recuperación de sus datos. Tienes que decidir dónde van a ser tus compensaciones.
fuente
corporation_id
yperson_id
entonces esencialmente tendría la solución de subtipado, excepto que la tabla de supertipo se habría dividido en dos y la clave externa se habría invertido, por lo que las personas no podrían tener varias cuentas. Este tipo de derrota el propósito.RefID
yRefTable
dondeRefTable
hay una identificación fija que identifica la tabla de destino. Hay muchos casos de uso para este tipo de clave y es demasiado para mantener 10 o más tablas de asociación / subtipo para hacer cumplir la integridad. Para esos casos, creé estokey
yo mismo.