Eu me deparei com um problema de design de banco de dados que está fora do meu alcance, e meu guru do DBA preferencial está fora de campo.
Em essência, eu tenho uma tabela com a seguinte chave primária (PK por brevidade):
child_id integer
parent_id integer
date datetime
child_id
e parent_id
são chaves estrangeiras para tabelas de entidades. A tabela "filho" em si também contém uma chave estrangeira para a tabela "pai", e eis que cada uma child_id
sempre faz referência à mesma parent_id
que o esperado pela tabela acima. Na verdade, acontece que há algum código extra mantendo os dois em sincronia.
O que faz esse novato de normalização super entusiasmado dizer "Devo remover a redundância!"
Decomponho o seguinte:
Table_1 PK:
child_id integer
date datetime
Table_2 PK:
parent_id integer
date datetime
Table_3: (already exists)
child_id integer PRIMARY KEY
parent_id integer FOREIGN KEY
E eis que, quando uno esses caras da maneira natural, recupero a tabela original. É o meu entendimento que torna este 5NF.
No entanto, agora percebo que há uma regra de negócios oculta.
Normalmente, as datas associadas a um determinado child_id
devem ser um subconjunto das datas associadas ao correspondente parent_id
. Você pode ver que a primeira tabela impõe essa regra.
Minha decomposição não impõe a regra, porque você pode adicionar livremente à Tabela 1 até que as datas fiquem muito grandes.
O que me leva aqui, com as seguintes perguntas:
Esta decomposição é 5NF? Embora eu diga que permite anomalias de inserção, também parece seguir o exemplo do Wiki, que segue este guia . A frase (ênfase minha) "podemos reconstruir todos os fatos verdadeiros a partir de uma forma normalizada que consiste em três tipos de registros separados" me dá uma pausa especial, pois, não importa a quantidade de lixo que eu bombeie
Table_1
, a junção natural ainda a ignora.Supondo que eu não goste desta decomposição (eu não). Reconheço livremente que a solução prática é deixar a tabela e o código como estão. Mas, em teoria, existe uma maneira de decompor e / ou adicionar restrições de modo que eu me afaste da primeira tabela e preserve minhas regras de negócios?
Respostas:
A normalização é baseada em dependências funcionais. Dependências funcionais têm a ver com semântica; eles têm a ver com o que os dados significam . Quando você simplifica um problema do mundo real para o nível "parent_id, child_id, date" e não inclui nenhum dado de amostra, você realmente limita a quantidade de ajuda que um designer de banco de dados consciente pode oferecer.
O fato de você ter uma chave {child_id, parent_id, date} em uma tabela e ter (ao que parece) um par exclusivo {child_id, parent_id} na tabela filho não significa necessariamente que parte da combinação é redundante . Isso pode significar que na tabela que possui {child_id, parent_id, date} como chave primária, o par de atributos {child_id, parent_id} deve fazer referência à tabela filho em primeiro lugar.
Se for esse o caso, você pode usar
FOREIGN KEY (child_id, parent_id) REFERENCES child (child_id, parent_id)
. Para fazer isso, você precisa de uma restrição UNIQUE no par de colunas (child_id, parent_id) na tabela "child", o que não deve ser um problema se child_id for sua chave primária.Mas não há como saber sem saber o que os dados significam, e você é o único nesse segmento que sabe disso. (Mas ficaríamos felizes em deixar você explicar isso para nós.)
No que diz respeito à tabela original, você parece estar dizendo que child_id -> parent_id. Se for esse o caso, por que parent_id está na tabela original em primeiro lugar? Por que a chave não é apenas (child_id, date), com uma referência de chave estrangeira à tabela "child"? Parece-me que o tipo de redundância de que você está falando pode ser resolvido soltando a coluna "parent_id".
SQL DDL e dados de amostra na forma de instruções INSERT nos ajudam a ajudá-lo. As instruções DDL e INSERT são mais precisas que as descrições.
fonte
Tente isso ...
(child_id,parent_id)
na tabela filho(PK,FK:child_id, PK,FK:parent_id, PK:date)
permanece como está, o FK está em 2 colunas para a nova restrição exclusivaou
(PK,FK:child_id, FK:parent_id)
1: 1 com filho(PK,FK: child_id, PK,FK: parent_id, PK:date)
permanece como está. mas o FK está em 2 colunas na nova tabelaSe nada mais, pode inspirar você ...
Se entendi corretamente, ele removerá redundância e código ...
fonte