2009-06-28 6 views
11

Ich entwerfe eine Datenbank für eine Organisation, die mehrere "Arten" von Benutzern hat. Zuerst habe ich nur eine Benutzertabelle erstellt. Während alle Benutzer einige gemeinsame Informationen teilen (Vorname, Nachname, Benutzername, Passwort usw.), benötigt jeder Benutzertyp ein oder zwei zusätzliche Felder, die nicht für alle Benutzer gelten. Während ich diese zusätzlichen Felder erstellen und sie als NULL setzen kann, möchte ich dies nicht tun, da die Felder Fremdschlüssel sind und für mich Probleme verursacht haben.MySQL Frage - Wie mit mehreren Arten von Benutzern zu behandeln - eine Tabelle oder mehrere?

Wie wird diese Situation normalerweise behandelt?

Danke!

Antwort

9

Ihre Instinkte ist rechts auf keine große Tabelle mit vielen NULLS zu erstellen. Das ist eine schlechte Idee, aus Sicht der Speicherung/Retraktivierung/Wartung, sowie aus Sicht der Datenvalidierung (mehr dazu später).

Die beiden häufigsten approcaches:

1) Haben Sie einen Benutzertabelle mit allen gängigen Bereichen darin, ein „usertype“ Feld darunter. Dann haben Sie für jeden Benutzertyp eine separate Tabelle, die die zusätzlichen Felder enthält. Alle Benutzer haben eine Zeile in der Benutzertabelle und eine oder mehrere der spezifischen Benutzertyptabellen. Dies ist am normalsten und am effizientesten für Speicherung und schnelle Logins. Auf diese Weise können Sie auch Beschränkungen und Fremdschlüssel verwenden, um sicherzustellen, dass alle erforderlichen Informationen für jeden Benutzertyp verfügbar sind.

2) Haben Sie eine Benutzertabelle mit allen allgemeinen Feldern darin. Haben Sie eine andere Tabelle namens UserAttributes, die Felder für Benutzer-ID, Schlüssel und Wert enthält. Alle zusätzlichen Metadaten für einen bestimmten Benutzer können hier gespeichert werden. Dies hat den Vorteil, dass keine Datenbankverwaltung neue Benutzertypen oder Metadaten für jeden Benutzertyp hinzufügen muss. Sie können jedoch keine Datenprüfung auf DB-Ebene durchführen.

+0

Danke, dj_segault. Ich ging mit Ihrer Option # 1, und erstellt eine Benutzertabelle mit den allgemeinen Feldern und einem userType-Feld, das durch die anderen, mehr "spezifischen" Benutzertabellen referenziert wird. Die NULLS haben definitiv Kopfschmerzen verursacht, ich bin froh, sie jetzt los zu sein! – littleK

+0

korrigieren Sie mich, wenn ich falsch liege (es passiert viel), aber wenn jemand ihre Daten so speichern würde, dass die gemeinsamen Felder auf einer "Benutzer" -Ebene wie fname, lname, email, pw ... und so weiter waren . Es gäbe keine Möglichkeit, mit einem einzigen Abfrage-Recht auf die benutzerspezifischen Informationen zuzugreifen. Es würde immer eine zweite Abfrage basierend auf dem Benutzertyp benötigen, um an spezifischere Informationen zu gelangen. – ackerchez

+0

@ackerchez Sicher gibt es. Alles, was Sie tun müssen, um ALLE Informationen zu erhalten, besteht darin, alle user-type-spezifischen Benutzertabellen mit der Haupt-Benutzertabelle zu verknüpfen, unabhängig von Ihrer UID. Die Spalten für die Tabellen, die nicht für diesen Benutzertyp sind, sind null. –

4

Das relationale Modell als solches unterstützt keine "Vererbung", was zur Lösung dieses Problems beitragen könnte (obwohl einige DB-Engines wie PostgreSQL Vererbung unterstützen).

Also würde ich mich zuerst fragen - müssen die verschiedenen Arten von Benutzern in der Lage sein, im selben Kontext zu erscheinen, zumindest in einigen Fällen? Wenn dies der Fall ist, können Sie die "gemeinsamen Spalten" nicht einfach in mehrere Tabellen kopieren und einfügen (zumindest nicht ohne die Integritätsprüfungen zu kompromittieren, die Sie in diesen Fällen über Fremdschlüssel auf eine einzige Tabelle erhalten könnten).

Zweite Frage - ist es überhaupt möglich für einen Benutzer, mehr als eine Rolle zu halten? In vielen Fällen wäre es ungewöhnlich, aber nicht absolut unmöglich, z.B. ein Mitarbeiter könnte auch ein Lieferant oder ein Kunde sein.

Wenn ich keine scharfen Antworten auf solche Fragen bekommen könnte, die mich anders leiten, würde ich eine Benutzertabelle mit nur den gemeinsamen Feldern einrichten; und separate Tabellen für Lieferanten, Mitarbeiter, Beta-Tester, Kunden und alle anderen Arten und Rollen, die ich für Benutzer haben könnte, jede mit nur ihren eigenen spezialisierten Spalten plus einem Fremdschlüssel auf dem Benutzertisch, um den Rest aufzuheben.

Ich weiß, dass normalisierte Schemas jetzt aus der Mode sind, aber sie haben mir jahrzehntelang treu gedient und ich habe eine tiefe Vorliebe für sie - ich denormalisiere nur, wenn ich spezifische Optimierungen benötige, und das passiert seltener als einer könnte denken!-).

Eine etwas Denormalisierung, die hier wahrscheinlich nützlich sein könnte, ist eine Aufzählungsspalte in der Benutzertabelle, die die "Haupt-" oder "einzige" Rolle jeder einzelnen Verwendung angibt (sie könnte Nullable sein und vielleicht gleich Null am Anfang, wenn I war aufdringlich genug, um es von Anfang an zu haben ...; -) ... aber ich würde wahrscheinlich warten, um es hinzuzufügen, wenn die Leistung einiger spezifischer Abfragen es als eine spezifische Optimierung brauchte, anstatt das Schema auf diese Weise zu entwerfen von Anfang an (beachten Sie, dass dies ein wichtiger Grund ist, nie SELECT * FROM in Ihren Abfragen zu verwenden - wenn Sie ALTER TABLE später eine Spalte hinzufügen, das SELECT * ist das eine Bit, das brechen würde! -).

+0

Alex, vielen Dank für Ihre Antwort, es hat mir wirklich geholfen. Ich habe getan, was Sie vorgeschlagen haben, und eine Tabelle mit den allgemeinen Feldern sowie separaten Tabellen für die anderen unüblichen Felder für jeden Benutzertyp eingerichtet. Ich habe auch eine Rollenaufzählungsspalte in der Benutzertabelle hinzugefügt. Danke! – littleK

1

Dies ist die berühmte Normalisierungsfrage.

Werfen Sie einen Blick auf diesen oder ähnliche Artikel, um eine Antwort zu finden, die den geschäftlichen Anforderungen entspricht.

To normalize or not to normalize

+0

Vielen Dank für den Artikel, fand es sehr hilfreich. Ich hatte so viele Fragen zu diesem Thema, und das beantwortete viele von ihnen. Danke! – littleK

+0

Going to a +1, aber der Link funktioniert nicht mehr. Möchten Sie es bitte aktualisieren? –

+0

@Gabriel Wow - Ich weiß nicht, ob es jemals funktioniert hat. Ich habe es auf den richtigen Artikel aktualisiert – Brian

0

Sie hat nicht gesagt, wenn Sie eine höhere Programmiersprache verwendet wurden, so dass ich nur ein allgemeines Beispiel mit DB-ähnlichem Beispiel:

Datenbank-Design ist hart. Also, das wird eine schnelle und einfache Antwort sein.

Ihre Frage ist eine grundlegende Frage über Datenbeziehungen und Datenbankdesign. Suchen Sie einige grundlegende Anleitungen, um diese Antwort zu unterstützen. Es kann hilfreich sein, darüber nachzudenken, wie Ihre Informationen gruppiert sind, und aus den anderen Sätzen (Tabellen) "zurück" mit dem primären Satz (Tabelle) zu verknüpfen.

Also, Benutzer sind Benutzer - das ist Ihre Tabelle. Es sollte die wichtigsten gemeinsamen Elemente (Spalten) von Daten enthalten, die einem Benutzer zugeordnet sind.

Dann ist diese andere Gruppe von Informationen (z. B. Berechtigungen oder etwas) eine andere Tabelle.

Stellen Sie sicher, dass diese andere Tabelle einen Wert (Spalte) hat, der auf den Benutzer verweist, auf den er sich bezieht. Sie werden wahrscheinlich wollen Ihre Datenbank sagen, einen „Index“ zwischen ihnen zu schaffen (Lookup-Leistungen zu verbessern, etc.)

zum Beispiel eine Art von „Erlaubnis“ Tabelle für den Anwender:

- 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 

So, Sie könnten "SELECT * FROM user_table WHERE first_name = 'joe' (oder so) ... um einen Benutzer zu bekommen. Dort würde ich hoffen, dass Sie eine Art 'ID' -Wert haben, um diese Zeile zu identifizieren.

Nun, tun Sie einfach eine 'SELECT * FROM Berechtigungen WHERE user_id =' nnnn '(was auch immer die ID dieses Benutzers ist).

Wenn ein Benutzer nur über 1 Berechtigungssatz verfügt, können Sie diese Benutzer-ID ohne die zusätzliche ID-Spalte haben.

+0

joej- Ich habe nie darüber nachgedacht, Berechtigungen auf der Datenbankebene auszudrücken. Sicher scheint eine gute Idee. Im Moment habe ich nur eine "Rolle" -Tabelle, die auf einen Benutzer verweist (und dann erzwinge ich diese Rolle mit PHP-Code). Ich mag deine Idee, aber ich habe vor, sie mehr zu benutzen. Danke! – littleK

Verwandte Themen