Anfängerfrage zur Tabellen-Architektur

Michi77

Benutzer
Beiträge
11
Mahlzeit!

In Sachen "Normalisierung" hatte ich mal gelernt, dass es Redundanzen zu vermeiden gilt und sich wiederholende Einträge in eine separate Tabelle ausgelagert werdne sollen (mal ganz banal formuliert).

Nun habe ich immer wieder mal Datenbanken gesehen, in deren Tabellen Einträge "ausgeschrieben" wurden, statt per Foreign-Key auf eine saparate Tabelle zu verweisen. Also z. B. so:

Name/Vorname/Gruppe
Meier/Anton/MENSCH
Rabbit/Roger/ TIER

statt

Name/Vorname/Gruppe
Meier/Anton/1
Rabbit/Roger/2

... mit einer separaten Tabelle "Gruppen" und dem entsprechenden Primary-Key.

Was hat es damit auf sich und welche Variante ist zu empfehlen?

Danke und viele Grüße!

Michael
 
Werbung:
Was hat es damit auf sich

Faulheit. Unwissen.

und welche Variante ist zu empfehlen?

Die richtige.

Ich denke mal, das hat auch geschichtliche Ursachen. MySQL konnte in früheren Versionen keine referentiellen Integritätschecks. Also das ganze Konzept von Fremdschlüsseln gab es nicht, in MyISAM. Und das wurde damals sogar noch als Vorteil dagestellt, bzw. daß man RI ja auch in der Applikation nachbilden könne.

Mittlerweile kann MySQL ja zumindest das. Check-Constraints oder gar (ich geb zu, das ist kompliziert) Exclusion Constraints, kann MySQL ja nach wie vor nicht. Ist halt nach wie vor eine doch stark beschränkte Datenbank bzw. der Versuch, eine DB zu sein.
 
Nun habe ich immer wieder mal Datenbanken gesehen, in deren Tabellen Einträge "ausgeschrieben" wurden, statt per Foreign-Key auf eine saparate Tabelle zu verweisen. Also z. B. so:

Name/Vorname/Gruppe
Meier/Anton/MENSCH
Rabbit/Roger/ TIER

statt

Nicht jeder Programmierer der eine Datenbank erstellt hat auch Ahnung vom richtigen Design einer Datenbank :)
 
Zuletzt bearbeitet:
Hi Michael.

Was hat es damit auf sich und welche Variante ist zu empfehlen?

Das kommt streng genommen auf die Art des Attributes an, da durch die Normalisierung Anomalien verhindern werden sollen. Da es sich in deinem Beispiel um wohl um eine Art "Flag" handelt macht es kaum einen Unterschied. Im Fall von MySQL dürfte Variante 1 mit ENUM-Feld sogar platzsparender sein.

Gruß
Hony
 
Variante 1 könnte
- schneller sein
- leichter abzufragen
- mehr Platz verbrauchen
- Alles davon
- Nichts davon
- Teile davon

Je nach Länge des Feldes, Anzahl der vorkommenden Varianten. Der Normalform entspricht es nicht, es verursacht Redundanz genau wie eine Tabelle PLZ / Ort. Deswegen ist so eine Tabelle aber nicht zwigend "schlecht" designt.
 
Wow - vielen Dank an alle für die schnellen und kompetenten Antworten!

Ich hab mir bisher gedacht, dass damit Abfragen einfach auch leichter zu lesen sind, da man statt Keys in Form von Zahlen den "Sinn" dahinter mehr oder weniger ausschreibt. In einem kürzlich gesehenen Beispiel war es konkret so eingesetzt, dass darüber die Gruppenzugehörigkeit von Usern bestimmt wurde. Das Ganze war in einem kommagetrennten String im Feld gespeichert, also z. B.

Gruppe
user,admin,team2

Ich hätte das wohl eher über Fremdschlüssel und dem Ergebnis

Gruppe
2,4,12

gelöst.
 
Stimmt, Komma-getrennte Multi-Wert Felder sind DB technisch gruselig. Referenzen auf andere Tabellen in solchen Feldern zu platzieren ist vermutlich nicht mehr zu unterbieten. Am Ende sieht man dann aber doch wieder derartige "Code"-Feldner im gängigen CMS deiner Qual.
 
Am Ende sieht man dann aber doch wieder derartige "Code"-Feldner im gängigen CMS deiner Qual.

Genau das!!

Die aktuelle Version des CMS TYPO3 verwaltet seine User über solche Felder bezüglich der Gruppenzugehörigkeit :D

Ich muss dann immer alles über FIND_IN_SET herausfiltern, was recht langsam sein dürfte...

Richtig wäre dann Auslagerung in eine dritte Tabelle, oder?

User (user_id, name)
Gruppen (gruppen_id, gruppe)
Gruppenzugehörigkeiten (user_id, gruppen_id)

Viele Grüße!

Michael
 
Dein CMS wird vermutlich nur "Gruppe 2,4,12" in der Tabelle ablegen und die Zuordnung Gruppen ID <-> Gruppenname irgendwie komplett selbst verwalten. Die DB dient also mehr als Speicher für Text, interpretieren tut es das CMS. Würde die DB diese Gruppen wirklich selbst relational abbilden wäre eine Zwischentabelle erforderlich.
 
OK, machen wir es doch mal konkret!

Ich will unser Intranet (basierend auf besagtem TYPO3) neu aufsetzen und stehe dabei vor der folgenden Herausforderung:

Einem User (Tabelle fe_user) sollen Zugriffsrechte auf bestimmte Datensätze zugeordnet werden, die sich nach seiner Hierarchie in seinem Betrieb richten. Es gibt User, die sollen nur Datensätze aus ihrer Abteilung sehen und es gibt User, die alle Datensätze für den gesamten Kunden sehen dürfen.

Welchen Bezug zum User schaffe ich jetzt hier am besten, damit ich bei Usern mit weiten Zugriffsrechten nicht tonnenweise Teilbereiche zuordnen muss?

Beispiele:

  • User Meier darf nur auf die Datensätze zu Filiale 3, Filiale 9 und Filiale 67 zugreifen
  • User Schmidt darf auf alle Filialen des Kunden zugreifen
Bisher habe ich das mit diesem beknackten FIND_IN_SET und endlosen CSVs gelöst, was die Abfragen ziemlich langsam gemacht hat. Kann ich das intelligenter lösen? Vielleicht mit einer Hierarchie in den Kunden-Entitäten?

Danke für jeden Tipp!

LG

Michael
 
OK, machen wir es doch mal konkret!

Ich will unser Intranet (basierend auf besagtem TYPO3) neu aufsetzen und stehe dabei vor der folgenden Herausforderung:

Einem User (Tabelle fe_user) sollen Zugriffsrechte auf bestimmte Datensätze zugeordnet werden, die sich nach seiner Hierarchie in seinem Betrieb richten. Es gibt User, die sollen nur Datensätze aus ihrer Abteilung sehen und es gibt User, die alle Datensätze für den gesamten Kunden sehen dürfen.

Welchen Bezug zum User schaffe ich jetzt hier am besten, damit ich bei Usern mit weiten Zugriffsrechten nicht tonnenweise Teilbereiche zuordnen muss?

Beispiele:

  • User Meier darf nur auf die Datensätze zu Filiale 3, Filiale 9 und Filiale 67 zugreifen
  • User Schmidt darf auf alle Filialen des Kunden zugreifen

Das ist nicht gerade trivial. Die sauberste Lösung dafür wären, daß Du die User so als DB-User anlegst. Dazu, daß diese User so erst einmal GAR KEINEN Zugriff auf die Tabellen haben, sondern nur über Funktionen. Innerhalb dieser prüfst Du die Zugriffsrechte.

Das ist aber a) nicht mal eben so realisierbar und b) wohl eher nicht unter der Haube eines anderen CMS, welches wohl weiter laufen soll. Ich hab sowas mal gesehen, bei Zalando. Aber, wie gesagt, da steckt 'ne Menge Arbeit dahinter, wenn es funktionieren soll.

Du kannst Dir aber das mal durchlesen:


sowie http://www.postgresql.org/docs/9.3/static/sql-createfunction.html und dort auf SECURITY DEFINER und andere Angaben zur Sicherheit achten.
 
Danke schonmal, akretschmer!

Meiner Einschätzung nach hätte ich wohl folgende Möglichkeiten
  • fe_users.zugriff_filialebene und fe_users.zugriff_kundenebene, wobei in diesen Feldern dann die Fremdschlüssel der Kunden/Filialen aufgelistet sind --> Werden dann halt wieder endlose CSVs und ich muss bei der Abfrage der Zugriffsrechte gleich zwei Felder berücksichtigen. Vorteil: Mit einem Verweis unter fe_users.zugriff_kundenebene hat der User Zugriff auf den gesamten Kunden, mühsames Zusammenklicken einzelner Filialen entfällt
  • Ich führe Hierarchien ein, indem aus Kunden und Filialen einfach "Bereiche" werden, die aufeinander aufbauen können (auch Kunden sind dann Bereiche, die als Untereinheiten Filialen haben) --> Könnte Abfragen schon recht kompliziert machen
  • Es gibt effektiv keine Kunden, sondern Benutzerrechte werden immer nur auf kleinster Ebene, also auf Filialebene erteilt --> Gibt ne mords Klickerei aber ist wohl das Sauberste
 
Nochmal ne eher allgemeine Frage: Empfiehlt es sich, die "verbindende Tabelle" ebenfalls mit einem Primärschlüssel auszustatten?

Also im obigen Beispiel die Tabelle, die z. B. Benutzer und deren Gruppen kombiniert.

Vielen Dank!
 
Werbung:
Zurück
Oben