Tabelas extras ou não-específicas chaves estrangeiras?
-
09-06-2019 - |
Pergunta
Existem vários tipos de objetos em um sistema, e cada um tem a sua própria tabela no banco de dados.O usuário deve ser capaz de fazer um comentário sobre qualquer um deles.Como você projetaria os comentários de tabela(s)?Eu posso pensar em algumas opções:
- Um comentários mesa, com um FK coluna para cada tipo de objeto (ObjectAID, ObjectBID, etc)
- Vários comentários tabelas, uma para cada tipo de objeto (ObjectAComments, ObjectBComments, etc)
- Um genérico FK (ParentObjectID) com outra coluna para indicar o tipo ("ObjectA")
Qual você escolheria?Não há melhor método que eu não estou a pensar?
Solução
@palmsey
Muito bonito, mas a variação no padrão que eu tenho visto na maioria das vezes se livrar de ObjectAID
et al. ParentID
torna-se tanto a PK e FK para Parents
.Que você fica algo como:
Parents
ParentID
ObjectA
ParentID
(FK e PK)ColumnFromA NOT NULL
ObjectB
ParentID
(FK e PK)ColumnFromB NOT NULL
Comments
continuaria a mesma.Em seguida, você só precisa restringir a geração de ID, de modo que você não acidentalmente acabar com um ObjectA
linha e uma ObjectB
linha que ambos apontam para o mesmo Parents
linha;a maneira mais fácil de fazer isso é usar a mesma sequência (ou qualquer outro) que você está usando para Parents
para ObjectA
e ObjectB
.
Você também verá um monte de esquemas com algo como:
Parents
ID
SubclassDiscriminator
ColumnFromA (nullable)
ColumnFromB (nullable)
e Comments
permaneceria inalterado.Mas agora você não pode impor a todos o seu negócio restrições (as subclasses' propriedades são todas nulo) e sem escrever gatilhos, ou fazê-lo em uma camada diferente.
Outras dicas
É possível projetar o esquema para que o commentable (por falta de uma palavra melhor) tabelas a seguir um padrão de herança-modelagem de padrões?Se assim for, você pode ter o comentário da tabela FK aponte para o pai comum de mesa.
@Hugo Gay
Algo assim como:
- ObjectA
- ObjectAID
- ParentID
- ObjectB
- ObjectBID
- ParentID
- Comentários
- CommentID
- ParentID
- Pais
- ParentID
Cuidado com genéricos chaves estrangeiras que não aponte para exatamente uma tabela.O desempenho da consulta sofre drasticamente se você tem que dividir a condição onde em um tipo e de um ponto para várias tabelas diferentes.Se você tiver apenas alguns tipos, e o número de tipos não vai crescer, é Ok ter separado chaves externas anuláveis as diferentes tabelas, mas se você tiver mais de um tipo, é melhor vir para cima com um diferente modelo de dados (como @palmsey sugestão).
Uma das coisas que eu mais gosto de fazer é ter um tabelas separadas que ligam o genérico/tabela comum a todos os individualizada tabelas.
Assim, para objetos Foo e Bar e, em seguida, comentários sobre Foo e Bar, você teria algo assim:
- Foo
- Foo ID (PK)
- Bar
- Barra de ID (PK)
- Comentário
- Comentário ID (PK)
- Comentário De Texto
- FooComment
- Foo ID (PK FK)
- Comentário ID (PK FK)
- BarComment
- Barra de ID (PK FK)
- Comentário ID (PK FK)
Esta estrutura:
- Permite que você têm em comum uma tabela de Comentários
- Não necessita de um DB com herança de tabela
- Não poluir o Foo e mesas de Bar, com Comentário de informações relacionadas com o
- Permite que você anexe um Comentário vários objetos (o que pode ser desejável)
- Permite que você anexe outras propriedades para a junção do Foo/Bar e Comentário, se assim o desejar.
- Ainda preserva as relações com o padrão (ou seja:simples, rápido, confiável) chaves estrangeiras