Eu não acho que você tenha um problema com os relacionamentos. Penso que, em vez disso, o problema é que, usando chaves substitutas (ou seja, IDs) para cada tabela, o banco de dados resultante é incapaz de impedir a inserção de trabalhadores cujo departamento é de uma empresa, enquanto a classificação é de outra e vice-versa. Uma boa maneira de entender isso é visualizar o esquema usando uma ferramenta de diagramação de ER. Vou usar o Oracle Data Modeler ferramenta que é um download gratuito.
Diagrama ER
Tal como está, você poderia ter duas empresas - digamos IBM
e Microsoft
. IBM
pode ter um Software Development
departamento e a Microsoft pode ter um Desktop Software
departamento. A IBM pode ter uma Software Engineer
classificação e a Microsoft pode ter uma Software Developer
classificação. Agora, porque você tem uma chave substituta para Department
e Classification
, o fato de Software Development
ser um IBM
departamento Desktop Software
é um Microsoft
departamento perdido para futuros relacionamentos com filhos. Este também é o caso com Classification
. Portanto, é fácil atribuir acidentalmente Harlan Mills
quem é IBM
funcionário do Software Development
departamento Software Developer
cuja classificação é umaMicrosoft
classificação! Da mesma forma, o trabalhador poderia receber a classificação correta e o departamento errado! Aqui está um diagrama mostrando o primeiro exemplo:
Os 1 IDs representam IBM
e os 2 IDs representam Microsoft
. Eu já destacados em vermelho o cenário onde Harlan Mills
e Bill Gates
são atribuídos aos departamentos erradas, que é visualizado pela Id 10 departamento associado à classificação 200 Id e vice-versa.
Opções para resolver
Então, quais são as opções para impedir que ele aconteça? Existem duas opções imediatas. A primeira é perceber que, usando uma chave substituta para todas as tabelas, esse problema existe e introduzir programação adicional para verificar se isso não ocorre. Isso pode ser feito no aplicativo, mas se inserções e atualizações puderem ocorrer fora do aplicativo, associações incorretas ainda poderão ocorrer. Uma abordagem melhor seria criar um gatilho que seja acionado na inserção e atualização de um funcionário para garantir que o departamento designado seja da mesma empresa que a classificação atribuída e, caso contrário, falhe na inserção ou atualização.
A segunda opção é não usar chaves substitutas para todas as tabelas. Em vez disso, use as chaves substitutas apenas para a Company
tabela, que é fundamental e não possui pais, e crie relacionamentos de identificação para as tabelas Department
e Classification
filhos. As tabelas Department
e Classification
agora têm uma PK do Company Id
número ou nome da sequência mais para distingui-las. Então, os relacionamentos de Department
e Classification
para Worker
também se tornam identifying
e, portanto, o PK de Worker
se torna o Company Id
, mais o Department Number
(estou usando um número de sequência neste exemplo), mais o Classification Number
. O resultado é que existe apenas one
Company Id
na Worker
tabela. Agora é impossível atribuir umWorker
para um Department
em um Company
e para um Classification
em outro Company
.
Por que isso é impossível? É impossível porque o esquema implementa integridade referencial entre Worker
e Department
e Classification
. Se for feita uma tentativa de inserir um Worker
para um Department
em um Company
e um Classification
de outro, a combinação que não existe na tabela pai correspondente disparará uma violação de integridade referencial e a inserção não funcionará.
Aqui está um diagrama atualizado de uma implementação da segunda opção:
Opção preferida
Das duas opções, prefiro absolutamente a segunda - usando os relacionamentos de identificação e as chaves em cascata - por dois motivos. Primeiro, esta opção atinge a regra desejada sem programação adicional. Desenvolver um gatilho não é trivial. Ele deve ser codificado, testado e mantido. Garantir que a lógica do acionador seja ideal para não afetar o desempenho também não é trivial. O livro Matemática Aplicada para Profissionais de Banco de Dados fornece muitos detalhes sobre a complexidade dessa solução. Segundo, as regras implicam que um Departamento e uma Classificação não podem existir fora do contexto do Company
e, portanto, o esquema agora reflete com mais precisão o mundo real.
Essa é uma ótima pergunta, pois mostra exatamente por que simplesmente supor que todas as tabelas exigem uma chave substituta é uma má idéia. Fabian Pascal tem um excelente post sobre este tópico, mostrando que uma chave substituta não só pode ser uma má ideia do ponto de vista da integridade de dados, como também pode resultar em lentidão nas recuperaçõesno nível físico, precisamente porque são necessárias junções que, se as chaves tivessem sido devidamente conectadas em cascata, seriam desnecessárias. Outro tópico interessante que essa pergunta revela é que um banco de dados não pode garantir que todos os dados inseridos nele sejam precisos em relação ao mundo real. Em vez disso, ele pode garantir apenas que os dados inseridos nele sejam consistentes com as regras declaradas a ele. Nesse caso, podemos fazer o melhor possível, usando a abordagem de chave em cascata para garantir que o DBMS possa manter os dados consistentes com relação à regra de que um Worker
de um dado Company
precisa ser atribuído Classification
e um Department
do mesmo Company
. Porém, se no mundo real Microsoft
houver um departamento chamado, Desktop Software
mas o usuário do banco de dados afirmar que o departamento estáSoftware Development
o DBMS não pode fazer nada além de assumir que foi dado um fato verdadeiro.