2009-06-28 12 views
11

Sto progettando un database per un'organizzazione che ha più "tipi" di utenti. Inizialmente, ho creato solo una tabella utente. Tuttavia, mentre tutti gli utenti condividono alcune informazioni comuni (nome, cognome, nome utente, password, ecc.), Ogni tipo di utente richiede uno o due campi aggiuntivi che non sono applicabili a tutti gli utenti. Mentre posso creare questi campi aggiuntivi e impostarli come NULL, non desidero farlo, poiché i campi sono chiavi esterne e causano problemi per me.Domanda MySQL - Come gestire più tipi di utenti: una tabella o più?

Come viene gestita normalmente questa situazione?

Grazie!

risposta

9

tuo istinto di non creare un grande tavolo con un sacco di NULLS è proprio sulla. Questa è una cattiva idea, da un punto di vista di archiviazione/retrival/manutenzione, oltre a un punto di vista di convalida dei dati (ne parleremo più avanti).

I due approcaches più comuni:

1) hanno una tabella utente con tutti i campi comuni in esso, tra cui un campo "UserType". Quindi disporre di una tabella separata per ciascun tipo di utente contenente i campi aggiuntivi. Tutti gli utenti hanno una riga nella tabella utenti e una o più tabelle specifiche per i tipi di utente. Questo è il più normalizzato e il più efficiente per lo storage e gli accessi rapidi. Ciò consente anche di utilizzare le contraffazioni e le chiavi esterne per assicurare che tutte le informazioni richieste per ciascun tipo di utente siano disponibili.

2) disporre di una tabella utente con tutti i campi comuni in essa contenuti. Avere un'altra tabella chiamata qualcosa come UserAttributes che contiene campi per userid, chiave e valore. Qui possono essere memorizzati tutti i metadati extra per un particolare utente. Questo ha il vantaggio di non richiedere alcuna amministrazione di database per aggiungere nuovi tipi di utente o metadati da memorizzare per ogni tipo di utente. Tuttavia, non consente di eseguire alcuna convalida dei dati a livello di DB.

+0

Grazie, dj_segfault. Sono andato con l'opzione n. 1 e ho creato una tabella utente con i campi comuni e un campo userType cui fanno riferimento le altre tabelle utente "specifiche". I NULI stavano sicuramente causando mal di testa, sono contento di liberarmene ora! – littleK

+0

correggimi se ho torto (capita molto) ma se qualcuno dovesse memorizzare i propri dati in modo tale che i campi comuni fossero a un livello "utente" come fname, lname, email, pw ... e così via . Non ci sarebbe modo di ottenere più informazioni specifiche dell'utente con una query, giusto? Ci vorrebbe sempre una seconda query basata sul tipo di utente per ottenere informazioni più specifiche. – ackerchez

+0

@ackerchez certo che c'è. Tutto quello che devi fare per ottenere TUTTE le informazioni è di unire internamente tutte le tabelle utente specifiche del tipo utente con la tabella utente principale, qualunque sia il tuo UID. Le colonne per le tabelle che non sono per quel tipo di utente saranno null. –

4

Il modello relazionale, in quanto tale, non sostenere "eredità", che potrebbe aiutare a risolvere questo problema (anche se alcuni motori DB, come PostgreSQL, supportano l'ereditarietà).

Quindi, prima mi chiedo: i diversi tipi di utenti devono essere in grado di apparire nello stesso contesto, almeno in alcuni casi? In tal caso, non puoi semplicemente copiare e incollare le "colonne in comune" su più tabelle (almeno non senza compromettere i controlli di integrità che potresti ottenere in questi casi tramite chiavi esterne su una singola tabella).

Seconda domanda: è sempre possibile per un utente per contenere più di un ruolo? In molti casi sarebbe insolito ma non completamente impossibile, ad es. un dipendente potrebbe anche essere un fornitore o un cliente.

Se non riuscissi a ottenere risposte precise a tali domande e non mi dirigesse diversamente, configurerei una tabella utenti con solo i campi comuni; e tabelle separate per fornitori, dipendenti, beta-tester, clienti e qualsiasi altro tipo e ruolo che potrei avere per gli utenti, ognuno con le proprie colonne specializzate più una chiave esterna sulla tabella degli utenti per raccogliere il resto. Mi rendo conto che gli schemi normalizzati sono fuori moda ora, ma mi hanno servito fedelmente per decenni e ho una profonda passione per loro - io denormalizzo solo quando ho bisogno di specifiche ottimizzazioni, e succede più raramente di uno potrebbe pensare!-).

Una sorta di denormalizzazione che potrebbe essere utile in questo caso è una colonna di enumerazione nella tabella degli utenti che indica il ruolo "principale" o "esclusivo" di ogni particolare utilizzo (potrebbe essere nullable e forse uniformemente null all'inizio, se io era abbastanza invadente da averlo dall'inizio ...; -) ... ma probabilmente aspetterei di aggiungerlo se e quando le prestazioni di alcune query specifiche lo richiedessero come ottimizzazione specifica, piuttosto che progettare lo schema in quel modo dall'inizio (notare che questo è un motivo chiave per non usare mai SELECT * FROM nelle tue query - se tu aggiungi ALTER TABLE in seguito a una colonna, quello SELECT * è l'unico che si romperebbe! -).

+0

Alex, grazie mille per la tua risposta, mi ha davvero aiutato. Ho fatto ciò che mi hai suggerito e ho impostato una tabella con i campi comuni, oltre a tabelle separate per gli altri campi non comuni per ogni tipo di utente. Ho aggiunto anche una colonna di enumerazione dei ruoli nella tabella degli utenti. Grazie! – littleK

1

Questa è la famosa domanda di normalizzazione.

Dai uno sguardo a questo articolo o ad altri simili per cercare di trovare una risposta adatta alle esigenze aziendali.

To normalize or not to normalize

+0

Grazie mille per l'articolo, trovato molto utile. Ho avuto così tante domande su questo argomento e questo ha risposto a molte di esse. Grazie! – littleK

+0

Dando un +1, ma il collegamento non funziona più. Volete aggiornarlo? –

+0

@Gabriel Wow - Non so se funzionasse mai. L'ho aggiornato all'articolo giusto – Brian

0

Lei non ha detto se si stesse utilizzando un linguaggio di alto livello, quindi mi limiterò a dare un esempio generale con DB-come ad esempio:

Progettazione di database è difficile. Quindi, questa sarà una risposta rapida e semplice.

La tua domanda è una domanda di base sulle relazioni dati e sulla progettazione del database. Cerca alcune guide di base per aiutare questa risposta. Può essere utile pensare a come le informazioni sono raggruppate e collegare "indietro" al set principale (tabella) degli altri gruppi (tabelle).

Quindi, gli utenti sono utenti - questo è il tuo tavolo. Dovrebbe contenere gli elementi (colonne) principali comuni dei dati associati a un utente.

Quindi, questo altro insieme di informazioni (ad es. Permessi o qualcosa) è un'altra tabella.

Assicurati solo che questa altra tabella abbia un valore (colonna) che rimandi all'utente, a cui fa riferimento. Probabilmente si vorrà dire al vostro database per creare un "indice" tra di loro (per migliorare le prestazioni di ricerca, etc.)

Ad esempio, una sorta di tabella "autorizzazione" per gli utenti:

- integer "id"  <--- unique, index column, auto-increment 
    - integer "user_id" <--- this is which user this belongs 
    - ... 
    - Boolean "can_write"   <--- example data column 
    - Boolean "can_read"   <--- example data column 
    - Boolean "can_reboot_system" <--- example data column 
    - etc, whatever you want 

Quindi, potresti "SELEZIONARE * FROM user_table WHERE first_name = 'joe' (o simile) ... per ottenere un utente.In là, mi auguro che tu abbia un qualche tipo di valore 'id' per identificare quella riga

Ora basta fare un 'SELECT * FROM autorizzazioni WHERE user_id =' nnnn '(qualunque sia l'id dell'utente)

Se un utente ha solo 1 permesso impostato, allora si può semplicemente avere user_id senza la colonna "id" aggiuntiva.

+0

joej- Non ho mai pensato di esprimere le autorizzazioni a livello di database. Sicuramente sembra una buona idea. In questo momento, ho solo una tabella "ruolo" che fa riferimento a un utente (e quindi impongo quel ruolo con il codice php). Comunque mi piace la tua idea, ho in programma di utilizzarla di più. Grazie! – littleK

Problemi correlati