Come modellare opzioni condivise e uniche per una famiglia di prodotti per un database relazionale?

1

Ho una famiglia di prodotti che attualmente ospita 3 linee di prodotti. Tutte e 3 le linee di prodotto condividono le stesse 4 opzioni, ma oltre a quelle, ciascuna linea di prodotti ha rispettivamente 1, 2 o 3 opzioni diverse, singole per quella linea di prodotti. Per illustrare:

+---------------------------------------------------+
| Product Family:                                   |
+---------------------------------------------------+
| Product Line 1 | Product Line 2 | Product Line 3  |
+----------------+----------------+-----------------+
| * Base Option1 | * Base Option1 | * Base Option1  |
| * Base Option2 | * Base Option2 | * Base Option2  |
| * Base Option3 | * Base Option3 | * Base Option3  |
| * Base Option4 | * Base Option4 | * Base Option4  |
+----------------+----------------+-----------------+
| * Ind Option X | * Ind Option Y | * Ind Option A  |
|                | * Ind Option Z | * Ind Option B  |
|                |                | * Ind Option C  |
+----------------+----------------+-----------------+

Come posso modellare quelli nel database relazionale?

Quello che ho ora è che ho una tabella chiamata category = {Linea prodotto 1, Linea prodotto 2, ..} e product = {Linea prodotto 1 - Modello A, Linea prodotto 1 - Modello B,. ..}

    
posta Dennis 30.03.2017 - 00:15
fonte

1 risposta

1

Questo sembra un caso valido per ereditarietà a tabella singola (STI) . (Supponendo che esista un caso "valido" per STI, vedi i miei contrappesi alla fine.)

Le basi di STI sono:

  1. Crea una tabella con il nome più astratto di tutte le classi ereditanti.
  2. Inserisci tutto delle colonne, sia condivise che univoche, in questa tabella.
  3. Aggiungi una colonna chiamata object_type (o il nome che preferisci, non mi piace type perché è usato in alcune lingue per ottenere il tipo di un oggetto e può causare conflitti di nomi).
  4. Nel codice, utilizza la colonna object_type per determinare quali colonne sono applicabili al record e annullare le altre.

Tuttavia, avendo già utilizzato STI, personalmente non ne sono un fan. Gli svantaggi di STI includono:

  1. Tabelle non normalizzate. Il passaggio 4 sopra dovrebbe alzare una bandiera rossa se sei esperto di database, in quanto è un indicatore immediato che questa tabella non è normalizzata bene.
  2. I dati non sono più auto-descrittivi come in un set di tabelle normalizzato. È difficile guardare questo tavolo singolo e determinare cosa ci sia effettivamente dentro. I campi null assumono nuove ambiguità. Questi valori sono nulli perché non sono applicabili al record o perché sono applicabili ma non abbiamo valori per loro?.
  3. Il refactoring di STI è molto più difficile rispetto all'impostazione di più tabelle per i dati nella progettazione iniziale. È anche pieno di rischi e sottigliezza, dal momento che devi migrare i vecchi dati nelle nuove tabelle. Ad esempio, se si utilizza un ORM per la migrazione dei dati, è possibile che il campo created_at nelle nuove tabelle possa mostrare la data corrente per tutti i record ricreati anziché la data originale. E indipendentemente dal fatto che tu usi un ORM, questo rigenererà anche tutte le chiavi surrogate generate automaticamente (se le stai usando) e potrebbe rompere le integrazioni esterne se quelle chiavi sono esposte o salvate ovunque (sebbene questa sia una cattiva idea di per sé, vedi la sezione "Non naturalizzare le chiavi surrogate" qui ). Questo e altri possibili "trucchi" potrebbero facilmente sorgere.
  4. Man mano che aumenti il numero di object_type supportato dalla singola tabella, tutti i consensi precedenti peggiorano.

STI fa funziona, ma è essenzialmente l'hacking del modello di dati per semplificare il codice contro piuttosto che configurare correttamente l'applicazione / ORM per utilizzare tabelle diverse.

L'alternativa a STI (e IMO la soluzione migliore a questo problema) consiste nell'utilizzare una tabella per gli attributi condivisi e altre tabelle per gli attributi univoci. Per il tuo caso:

Tabelle (nominali come meglio ha senso):

  1. shared_product_line_options contenente le opzioni di base 1-4
  2. product_line_one contenente l'opzione X Ind
  3. product_line_two contenente Ind Options Y e Z
  4. product_line_three contenente le opzioni A, B e C

Inserisci una chiave esterna in ogni tabella product_line che punta alla tabella shared_product_line_options .

    
risposta data 09.04.2017 - 07:47
fonte