Bancos de dados relacionais não são criados para lidar com essa situação perfeitamente. Você precisa decidir o que é mais importante para você e depois fazer suas trocas. Você tem vários objetivos:
- Manter a terceira forma normal
- Manter a integridade referencial
- Mantenha a restrição de que cada conta pertence a uma corporação ou a uma pessoa natural.
- Preserve a capacidade de recuperar dados de maneira simples e direta
O problema é que alguns desses objetivos competem entre si.
Solução de sub-digitação
Você pode escolher uma solução de sub-digitação na qual cria um super-tipo que incorpora empresas e pessoas. Esse supertipo provavelmente teria uma chave composta da chave natural do subtipo mais um atributo de particionamento (por exemplo customer_type
). Isso é bom no que diz respeito à normalização e permite impor a integridade referencial, bem como a restrição de que empresas e pessoas sejam mutuamente exclusivas. O problema é que isso dificulta a recuperação de dados, porque você sempre precisa se ramificar customer_type
quando se associa à conta do titular da conta. Provavelmente, isso significa usar UNION
e ter um monte de SQL repetitivo na sua consulta.
Solução com duas chaves estrangeiras
Você pode escolher uma solução na qual mantenha duas chaves estrangeiras na tabela da sua conta, uma para a corporação e outra para a pessoa. Essa solução também permite manter a integridade referencial, a normalização e a exclusividade mútua. Ele também tem a mesma desvantagem de recuperação de dados da solução de sub-digitação. De fato, esta solução é como a solução de sub-digitação, exceto que você começa o problema de ramificar sua lógica de junção "mais cedo".
No entanto, muitos modeladores de dados considerariam essa solução inferior à solução de sub-digitação devido ao modo como a restrição de exclusividade mútua é imposta. Na solução de sub-digitação, você usa chaves para impor a exclusividade mútua. Na solução de duas chaves estrangeiras, você usa uma CHECK
restrição. Conheço algumas pessoas que têm um viés injustificado contra restrições de cheques. Essas pessoas preferem a solução que mantém as restrições nas chaves.
Solução de atributo de particionamento "não-normalizado"
Há outra opção em que você mantém uma única coluna de chave estrangeira na tabela de contas chequing e usa outra coluna para informar como interpretar a coluna de chave estrangeira (RoKa'sOwnerTypeID
coluna). Isso basicamente elimina a tabela de supertipo na solução de sub-digitação, desnormalizando o atributo de particionamento para a tabela filho. (Observe que isso não é estritamente "desnormalização" de acordo com a definição formal, porque o atributo particionamento faz parte de uma chave primária.) Essa solução parece bastante simples, pois evita que uma tabela extra faça mais ou menos a mesma coisa e reduz o número de colunas de chave estrangeira para um. O problema com esta solução é que ela não evita a ramificação da lógica de recuperação e, além disso, não permite que você mantenha a integridade referencial declarativa . Os bancos de dados SQL não têm a capacidade de gerenciar uma única coluna de chave estrangeira para uma das várias tabelas pai.
Solução de domínio de chave primária compartilhada
Uma maneira de as pessoas às vezes lidarem com esse problema é usar um único pool de IDs, para que não haja confusão para um determinado ID, independentemente de pertencer a um subtipo ou outro. Provavelmente, isso funcionaria naturalmente em um cenário bancário, pois você não emitirá o mesmo número de conta bancária para uma corporação e uma pessoa natural. Isso tem a vantagem de evitar a necessidade de um atributo de particionamento. Você pode fazer isso com ou sem uma tabela de supertipo. O uso de uma tabela de supertipo permite usar restrições declarativas para impor exclusividade. Caso contrário, isso teria que ser aplicado procedimentalmente. Essa solução é normalizada, mas não permitirá que você mantenha a integridade referencial declarativa, a menos que mantenha a tabela de supertipo. Ainda não faz nada para evitar lógica de recuperação complexa.
Você pode ver, portanto, que não é realmente possível ter um design limpo que siga todas as regras, mantendo ao mesmo tempo a recuperação de dados simples. Você tem que decidir onde serão suas compensações.
OwnerTypeID
naChecquingAccount
tabela, com1=Corporation
e2=NaturalPerson
? Dessa forma, você só precisa de umOwnerID
naChecquingAccount
tabela, que pode ser indexado junto com oOwnerTypeID
.