Die Flagge des Marasek

Dekostreifen

English

Aktuell Texte Der Comic Impressum Kalender Suche PHP-Klassen Container-Wizard main.s21

Kategorien

Buch
Computer
Computerspiele
Film
Geschichte
Gesellschaft
Idee
Kunst
Natur
Persönlich
Politik
Programmieren
Religion & Philosophie
Weblog
Weltpolitik
Weltsicht
{{login}}

Anmerkungen zum Datenbankdesign

Permalink
Vorheriger: ElsternNächster: Katzenethik, Hundeethik
Eingeordnet in: Computer, Programmieren

Ich arbeite jetzt seit etwa vier Jahren mit SQL-Datenbanken. Zunächst mit MySQL, dann seit etwa April 2003 vermehrt mit PostgreSQL. Professionelle Sachen entwickle ich nur noch mit PostgreSQL. Allerdings ist MySQL besser geworden, seit dem es InnoDB mit Transaktionen und Referentieller Integrität gibt.
Generell normalisiere ich recht streng. Zu Zeiten von MySQL war ich da etwas nachlässiger, da grössere Abfragen unter MySQL ein Kreuz sind. Eine schöne Abfrage kann sich durchaus mal über 15-20 Tabellen erstrecken, wobei ich unter PostgreSQL meine vordefinierten Sichten habe, die ich nur noch zusammenführen muss. Dazu habe ich mir ein sehr strenges Benennungsschema angewöhnt. Seitdem ich mich damit konfrontiert sah, Abfragen von einer grösseren, selbstverständlich weitgehend undokumentierten Datenbank zu machen, deren Primärsschlüssel für gewöhnlich einfach nur ID hiessen, weiss ich, was eine logische Benennung ausmacht. Ausserdem heisst bei mir der Primärschlüssel genau so wie der Fremdschlüssel, um bei Abfragen das wesentlich übersichtlichere ... JOIN ... USING (schlüssel) anstelle des trägen ... JOIN ... ON (tabelle1.primärschlüssel = tabelle2.fremdschlüssel) verwenden zu können, und zwar konsequent.

Bennennung von Tabellen

Grundsätzlich gibt es für mich drei wesentliche Tabellentypen: Datensatz (d wie data), Verknüpfung (n wie node) und Liste (l wie list). Daher heissen alle meine Tabellen entsprechend: d_person, d_user, l_gender, n_person2user. Die einzelnen Spalten nenne ich abhängig von ihrem Typ (l,n,d) und nehme noch ein kurzes Präfix, das den Namen der Tabelle repräsentiert, also z. b. lge_ bei der Listentabelle l_gender.

Datensätze
Als Datensatz behandle ich alles, was im wesentlichen wirkliche Nutzdaten speichert, beispielsweise Personen, Adressen, Texte. Der Name einer Personentabelle ist für mich also z. b. d_person. Vom Aufbau her bringe ich zunächst den Primärschlüssel, dann alle Attribute und zuletzt etwaige Fremdschlüssel unter:

table d_person
du_id serial (oder int mit auto_increment für mysql),
dp_name,
dp_surname,
lge_id
lti_id

Danach folgen natürlich die Constraints: Primary für den Primärschlüssel, und in diesem Fall Foreign für lge_id und lti_id.

Listen
Listentabellen enthalten normalisierte Attribute von Datentabellen, die selbst keinen wesentlichen Datencharakter haben. Zur Unterscheidung: Geschlecht und Titel einer Person gehören normalisiert in eine Listentabelle, die Adresse kann man entweder als Attribut der Person speichern oder in einer anderen Datentabelle speichern.
Als Beispiel für eine Listentabelle:

table l_gender:
lge_id serial,
lge_gender
deprecated

Danach folgt der Primärschlüssel für lge_id und ein Unique-Constraint auf lge_gender.
"deprecated" dient in diesem Zusammenhang als Hinweis für veraltete Listeneinträge. Diese sollen als aktuelle Auswahl nicht mehr gezeigt werden (im Frontend), aber nachwievor im System existieren, für ältere Datensätze. deprecated hat kein Präfix, damit das Frontend überall auf den gleichen Namen zurückgreifen kann, wenn es z. b. ein Dropdown erstellt.

Verknüpfungen
Verknüpfungstabellen dienen dazu, n:m-Beziehungen herzustellen. Nehmen wir einmal an, wir haben Branchen (gespeichert in l_branch) zu denen Personen gehören können (d_person), und zwar so, dass eine Person in mehreren Branchen vertreten sein kann:

table n_person2branch:
n_id serial,
dp_id,
lbr_id

Natürlich kommen entsprechende Foreign Keys drauf, und zwar so, dass dp_id ON DELETE CASCADE ist, aber lbr_id ON DELETE RESTRICT. Dadurch wird der Eintrag "aufgeräumt" bzw. gelöscht wenn die Person verschwindet, die Branche kann aber nicht entfernt werden, solange noch eine Person dazugehört. Zu bemerken ist, dass ich bei n_id keine Eindeutigkeit verwende - bislang musste ich noch nie auf n_id selbst als Fremdschlüssel referenzieren, daher muss n_id auch nicht eindeutig sein.
Die Reihenfolge ist für mich immer Datensatz zu Liste, was sich auch im Namen (n_person2branch) widerspiegelt. Verknüpfe ich zwei Datensätze, mache ich es von der Oberfläche abhängig. Der "Listenartigere" der beiden Datensätze kommt meist nach rechts.

Sichten
Sichten benenne ich meist mit v_, es sei denn, ich nutze sie, um aus Datensätzen eine Liste generieren zu lassen. Typisches Beispiel sind Projekte, die als l_project für ein Dropdown verwendet werden. Mit PostgreSQL's CASE-Funktionen kann man sogar so weit gehen, nicht mehr aktuelle Projekte als "deprecated" in der Sicht zu verwenden.
Teilweise habe ich mehrere grosse Sichten, die meine Benutzer dann im Frontend parametrisieren können. Zur Übersicht bei der Abfrage habe ich mehrere Sichten ineinander geschachtelt, was mit PostgreSQL problemlos geht. Jedoch ist dann jede Änderung mit einem grossen Aufwand verbunden.

Frontend

Mit einer derartigen Struktur ist ein Frontend fast ein Klacks. Man hat die Datenbank im wesentlichen für zwei Aufgaben: Daten eingeben, Daten ausgeben. Ist eine einheitliche Datenstruktur verlässlich implementiert, kann man einige kompakte Klassen für die Ein- und Ausgabe programmieren. Wichtig ist dabei, dass man die Datenbank Datenbankaufgaben erledigen lassen kann, und das Frontend nur noch Aufgaben übernimmt, die Dateneingabe aufzubereiten und zu überprüfen oder die Ausgabe hübsch darzustellen.
Auch wenn man mal manuell mit der Datenbank arbeiten muss - etwa für spezialisierte Abfragen oder um Daten zu importieren oder zu erweitern - hilft die Struktur, viel Zeit zu sparen, die man sonst mit der Enträtselung der einfachsten Zusammenhänge verbringen darf.

Kommentieren

Bitte beachten: Kommentare sind nicht sofort sichtbar, sondern werden erst nach einer kurzen Prüfung freigegeben, sofern keine rechtliche Beanstandung vorliegt.
Rechtlich bedenkliche Inhalte werden entweder entschärft oder nicht veröffentlicht.

* Titel  
* Nickname  
* Kommentar