Progettazione del database: dove archiviare un flag "corrente" o "selezionato" in una gerarchia padre-figlio [duplicato]

0

Mi spiace, forse è un principio di design ben noto, ma poiché non conosco un nome per questo tipo di relazione, non sono stato in grado di trovare alcuna risposta esistente.

Quindi, diciamo che abbiamo un genitore che può avere molti figli, ma solo un figlio può avere qualche proprietà attiva (o impostata). Pensa a proprietà come "selezionato", "corrente", "attivo", "predefinito", ecc. Quindi, la mia domanda è dove memorizzare questo flag?

La variante 1 è di memorizzarla come proprietà figlio, come questa:

+---------+----------+--------------+-------------+
| ChildId | ParentId | SomeProperty | _IsCurrent_ |
+---------+----------+--------------+-------------+
|       1 |        1 | A            | False       |
|       2 |        1 | B            | True        |
|       3 |        1 | C            | False       |
|       4 |        2 | A            | True        |
+---------+----------+--------------+-------------+

La variante 2 è di memorizzarla come proprietà genitore:

+----+--------------+------------------+
| Id | SomeProperty | _CurrentChildId_ |
+----+--------------+------------------+
|  1 | A            |                2 |
|  2 | B            |                4 |
+----+--------------+------------------+

E la variante 3 è di memorizzarlo in entrambe le tabelle.

Quindi quale variante è quella giusta? Ho sempre usato la variante 1, ma ora penso che forse questa è una cattiva pratica perché puoi finire con 2 articoli correnti, ecc. E qual è il nome corretto per questo tipo di proprietà?

P.S. Penso che non sia rilevante, ma nel caso, sto usando SQL Server.

P.S. 2. Ho trovato una domanda simile qui , che hanno 2 risposte, ma nessuna è accettata e suggeriscono cose opposte. Quindi se nessuno risponderà a questa domanda, probabilmente lo eliminerò presto. Oppure i moderatori possono sentirsi liberi di cancellare questa domanda in qualsiasi momento, se lo desiderano.

    
posta graycrow 30.05.2018 - 13:07
fonte

1 risposta

3

La variante 2 è una scelta sbagliata perché crea un riferimento circolare che generalmente dovrebbe essere evitato. Inoltre, non segue le pratiche di normalizzazione perché l'id figlio potrebbe essere esso stesso una chiave per il genitore in uno a molti scenari e non è direttamente correlato al genitore. Eliminare i bambini è più problematico in questo scenario poiché è necessario aggiornare prima il genitore.

La variante 1 può essere eseguita, ha ancora problemi di normalizzazione poiché l'indicatore isPrimary dipende dai valori di altre righe. È possibile gestire questo con un trigger per controllare sempre dopo le modifiche, questa è ancora una soluzione piuttosto disordinata. Gli aggiornamenti di isPrimary richiedono sempre due istruzioni e l'inserimento di nuovi figli richiede il controllo del contenuto della tabella.

Il modo completamente normalizzato per risolvere questo problema consiste nell'avere una tabella PrimaryChild con colonne id padre e figlio. È possibile applicare l'univocità all'id del genitore in questa tabella per garantire che un genitore abbia un solo figlio primario. questa soluzione, pur normalizzata, presenta uno svantaggio del fatto che la lettura è più complicata in quanto avrete sempre bisogno di 2 o 3 tavoli. L'eliminazione di un record figlio può essere stabilita in cascata e gli aggiornamenti del figlio primario sono anche più semplici.

La soluzione migliore dipende in realtà dalle tue esigenze individuali e da dove sei disposto a mantenere la complessità. La terza opzione è probabilmente la migliore a meno che leggere le prestazioni non sia un problema, nel qual caso dovresti scegliere una delle altre 2 opzioni. Quale opzione scegliere dipenderà dal tuo caso d'uso e dalla complessità / potenziali anomalie che sei disposto ad accettare.

    
risposta data 30.05.2018 - 15:05
fonte

Leggi altre domande sui tag