Tabelle extra o chiavi esterne non specifiche?
-
09-06-2019 - |
Domanda
Esistono diversi tipi di oggetti in un sistema e ognuno ha la propria tabella nel database.Un utente dovrebbe essere in grado di commentare ognuno di essi.Come progetteresti le tabelle dei commenti?Mi vengono in mente alcune opzioni:
- Una tabella dei commenti, con una colonna FK per ogni tipo di oggetto (ObjectAID, ObjectBID, ecc.)
- Diverse tabelle di commenti, una per ogni tipo di oggetto (ObjectAComments, ObjectBComments, ecc.)
- Un FK generico (ParentObjectID) con un'altra colonna per indicare il tipo ("ObjectA")
Quale sceglieresti?C'è un metodo migliore a cui non sto pensando?
Soluzione
@palmsey
Più o meno, ma la variazione di quello schema che ho visto più spesso viene eliminata ObjectAID
et al. ParentID
diventa sia PK che FK Parents
.Questo ti dà qualcosa come:
Parents
ParentID
ObjectA
ParentID
(FK e PC)ColumnFromA NOT NULL
ObjectB
ParentID
(FK e PC)ColumnFromB NOT NULL
Comments
rimarrebbe lo stesso.Quindi devi solo limitare la generazione dell'ID in modo da non ritrovarti accidentalmente con un file ObjectA
riga e un ObjectB
riga che puntano entrambi allo stesso Parents
riga;il modo più semplice per farlo è utilizzare la stessa sequenza (o qualsiasi altra cosa) per cui stai utilizzando Parents
per ObjectA
E ObjectB
.
Vedi anche molti schemi con qualcosa come:
Parents
ID
SubclassDiscriminator
ColumnFromA (nullable)
ColumnFromB (nullable)
E Comments
rimarrebbe invariato.Ma ora non puoi applicare tutti i tuoi vincoli aziendali (le proprietà delle sottoclassi sono tutte annullabili) senza scrivere trigger o farlo a un livello diverso.
Altri suggerimenti
È possibile progettare lo schema in modo che le tabelle commentabili (in mancanza di una parola migliore) seguano uno dei modelli standard di modellazione dell'ereditarietà?Se è così, puoi fare in modo che l'FK della tabella dei commenti punti alla tabella genitore comune.
@Hank Gay
Quindi qualcosa del tipo:
- OggettoA
- ObjectAID
- ID genitore
- OggettoB
- OggettoBID
- ID genitore
- Commenti
- ID commento
- ID genitore
- Genitori
- ID genitore
Fai attenzione alle chiavi esterne generiche che non puntano esattamente a una tabella.Le prestazioni delle query risentono notevolmente se è necessario suddividere la condizione where su un tipo e puntare a diverse tabelle diverse.Se hai solo pochi tipi e il numero di tipi non aumenterà, va bene avere chiavi esterne nullable separate per le diverse tabelle, ma se avrai più tipi, è meglio trovare un modello di dati diverso (come suggerimento di @palmsey).
Una delle cose che mi piace fare è avere tabelle separate che colleghino la tabella generica/comune a tutte le tabelle personalizzate.
Quindi, per gli oggetti Foo e Bar e quindi i commenti su Foo & Bar, avresti qualcosa del genere:
- Pippo
- ID cibo (PK)
- Sbarra
- ID barra (PK)
- Commento
- ID commento (PK)
- Testo del commento
- FooComment
- ID del cibo (PK FK)
- ID commento (PK FK)
- BarCommento
- ID barra (PK FK)
- ID commento (PK FK)
Questa struttura:
- Consente di avere una tabella Commenti comune
- Non richiede un DB con ereditarietà delle tabelle
- Non inquina le tabelle Foo e Bar con informazioni relative ai commenti
- Consente di allegare un commento a multiplo oggetti (che possono essere desiderabili)
- Consente di allegare altre proprietà alla giunzione di Foo/Bar e Comment, se lo si desidera.
- Conserva ancora le relazioni con lo standard (es:veloce, semplice, affidabile) chiavi esterne