Information ausblenden
Willkommen im Forum für alle Datenbanken! Registriere Dich kostenlos und diskutiere über DBs wie Mysql, MariaDB, Oracle, Sql-Server, Postgres, Access uvm

Modellierung meiner Datenbank

Dieses Thema im Forum "Datenmodellierung, Datenbank-Design" wurde erstellt von Sophus, 30 November 2014.

  1. Sophus

    Sophus Datenbank-Guru

    Hallo Leute,

    nachdem ich nun ein geeignetes und kostenloses Programm (Dia) gefunden habe, möchte ich mit euch zusammen nun in kleinen Schritten beginnen meine Datenbank zu modellieren.

    Für diejenigen, die es noch nicht wissen, geht es hier zunächst einmal um eine Film-Serie Datenbank. Eine Datenbank, in welcher Informationen über Filme und Serien gespeichert werden. Beginnen möchte ich mit der Person, die in Filmen und Serien als Schauspieler dienen.

    xaphusfilmservm5oe4iyjc.jpg

    So, was sehen wir hier? Wir sehen erst einmal fünf Tabellen (Nationalität, Geschlecht, Geburtsort, Status, Person) und eine Zwischentabelle (Nationalität_Person).

    Die Tabellen Geschlecht und Geburtsort sind selbsterklärend. Jedoch möchte ich kurz darauf eingehen, weshalb ich sie ausgelagert habe. Mir geht es allgemein darum, dass ich in meiner Datenbank Redundanten vermeiden will. Darüber hinaus möchte ich einen Datensatz in Real auch nur einmal ändern. Beispiel, ich habe in mich in der Tabelle Geschlecht vertippt, anstatt "männlich" habe ich "mnnälich" geschrieben, und mir fällt es wesentlich später auf, während ich angenommen schon 100 Datensätze habe. So müsste ich alle 100 Datensätze abarbeiten oder einen kleinen Code in meinem Programm schreiben, der die Datensätze nacheinander ausliest, und sie entsprechend ändert. In meinem Fall brauche ich aber nur einmal eine Korrektur bzw. Änderung vornehmen, und die Änderung bzw. Korrektur ist dann auch in anderen 100 Datensätzen wirksam. Des Weiteren betrachte ich diese beiden Tabellen, Geschlecht und Geburtsort, als Stammdaten.

    In der Tabelle Status kommt nicht, wie vermutet der Beziehungsstatus rein, sondern der Status darüber, ob die Person bzw. der Schauspieler bereits tot ist oder noch lebt. Wenn er tot ist, wird auch sein Todeszeitpunkt vermerkt.

    Kommen wir nun zur Nationalität. Ich habe mich ein wenig schlau gemacht, und mich gefragt, wie viele Nationalität ein Mensch besitzen kann? Nach meiner logischen Berechnung komme ich auf drei. Angenommen das Kind kommt in Amerika zur Welt, der Vater des Kindes ist Deutscher, und die Mutter des Kindes ist Spaniern. Also haben wir hier folgende Konstellation. Eine Person kann mehrere Nationalität besitzen, und eine Nationalität kann von mehreren Personen beansprucht werden. Also viele Personen viele Nationalitäten und andersrum. Daher die Zwischentabelle Nationalität_Person.

    Anmerkungen: Euch ist sicherlich aufgefallen, dass ich nicht mit Beziehungs-Bezeichnungen wie 1:n oder n:m arbeite. Der Hintergrund ist folgender: Ich bin der Ansicht, dass in Datenbanken heutzutage keine Beziehungen mehr eingearbeitet werden müssen. Die Datenbanken werden auf der Seite meines Projektes erstellt und strukturiert. Hinzu kommt, dass das Anlegen und Abrufen von meinem Projekt aus stattfindet. Des Weiteren ist euch sicherlich aufgefallen, dass bei allen ID-Feldern, die als PK (Primary Key) deklariert worden sind, den Feldtyp Long Integer haben, und nicht AutoIncrement. Das liegt daran, dass mein Programm die IDs vergibt. Ich werde dabei in meinem Programm mit der GUID arbeiten.

    Jetzt seid ihr am Zug. Ich freue mich über eure Anmerkungen und Kritik sowie Verbesserungsvorschläge.

    Euro Sophus
     
    Zuletzt von einem Moderator bearbeitet: 30 November 2014
  2. Hony%

    Hony% Datenbank-Guru

    Dieses »Problem« ließe sich auch durch einen ENUM-Typ oder einen CHECK-Constraint behandeln. Selbst bei circa 60 Geschlechtern, wie bei Facebook, halte ich den Nutzen einer eigenen Relation eher für fraglich.

    Welchen effektiven Nutzen erhoffst du dir von der Auslagerung? Streng genommen kann der Status auch als Boolscher Wert direkt in der Relation Person gespeichert werden. Der einzige für mich ersichtliche Vorteil wäre nur für Verstorbene einen Eintrag hinzuzufügen um ein paar wenige Byte Speicherplatz zu sparen.

    Wie ein künstlicher Schlüssel erzeugt wird spielt keine Rolle, solange er seine Aufgabe erfüllen kann.

    Woran ich mich ehrlich gesagt mehr störe ist die, meiner Ansicht nach, sinnlose künstliche ID bei Nationalität_Person sowie Geschlecht. Ebenso kann man über die Notwendigkeit der ID der Relation Nationalität diskutieren.

    In den Relationen Geschlecht und Nationalität sollten die Bezeichnungen selbst schon eindeutig und damit als PK geeignet sein. Änderungen können problemlos per CASCADE an die referenzierenden Relationen weitergegeben werden.

    In der Relation Nationalität_Person ist die Kombination aus Person_ID und Nationalität(_ID) bereits eindeutig und als PK geeignet.

    Ein Verzicht auf die künstliche ID wäre mit keinerlei Einschränkung verbunden. Durch die künstliche ID selbst aber können zusätzliche Probleme entstehen. In deinem Fall wäre ein netter Nebeneffekt, dass du bei der Abfrage selbst auf einige JOINs verzichten könntest, da die Informationen aus dem FK bereits ausreichend sind.

    Müssen natürlich nicht. Aber warum willst du eine ursprüngliche Aufgabe einer Datenbank auslagern und das Rad neu erfinden? Glaubst du wirklich, dein Programm könnte diese Aufgabe besser erledigen?
     
    Walter und akretschmer gefällt das.
  3. Sophus

    Sophus Datenbank-Guru

    Ehrlich gesagt, habe ich diesen Lösungsansatz nicht verstanden. Beziehst du dich hierbei auf die Seite des Programms oder auf die Datenbank-Funktionen? Wenn du dich auf die Programm-Seite beziehst, gestaltet sich die Problemlösung etwas komplizierter. Denn ich biete in meinem Programm gleich mehrere Sprachen an. Bevor ich mir also einen Enum-Typ erarbeite, wäre es für mich die Lösung mit der Geschlecht-Tabelle angenehmer.

    Stimmt, man könnte True für "lebt noch" und False für "Tod" einsetzen, und den Todeszeitpunkt in die selbe Tabelle Person abspeichern.

    Abfragen und Suchen laufen meistens über IDs, da sie am schnellsten sind. Es gibt einige mehr als zwei Nationalitäten auf der Welt. Und im Falle der Zwischentabelle Nationalität_Person braucht man also die ID von der Nationalität. Zu der frage, weshalb die Zwischentabelle Nationalität_Person eine - um dich mal zu zitieren - künstliche und sinnlose ID bekommt. Ist es nicht Standard, dass Zwischentabellen selbst ein ID-Feld bekommen?

    Ich werde bei Abfragen immer auf FKs zugreifen.

    Also, bei Microsoft Access arbeitet man sehr gerne mit Beziehungen. In meinem Programm sollen gleich mehrere Datenbanken unterstützt werden, darunter auch MySQl. Und soweit ich informiert bin, gibt es dort keine Beziehungen. Man arbeitet einfach mit den PKs und FKss und trommelt seine Informationen auf der Seite der Software zusammen. Also werde ich diese Art zu arbeiten bei all den anderen Datenbank gleich handhaben, auch bei Access.
    ----------------------------------------------------------------------------

    Nachdem ich einige deiner Ratschläge berücksichtigt habe, sieht meine Modellierung wie folgt aus:

    xaphusfilmserm6og3bksqu.jpg
     
    Zuletzt von einem Moderator bearbeitet: 1 Dezember 2014
  4. Hony%

    Hony% Datenbank-Guru

    Ich meine damit nur die Datenbank. ENUM als Datentyp wird zum Beispiel von PostgreSQL oder MySQL unterstützt. MS-SQL hingegen kennt keinen ENUM-Typ. Hier müsste man mit einem CHECK arbeiten. Wenn du nur mit 2-3 Geschlechtern arbeitest dürften diese Alternativen deutlich schneller sein als eine zusätzliche Tabelle.

    Ich wollte dir damit eigentlich nur aufzeigen, dass es mehr als nur einen Weg gibt Tippfehler zu vermeiden.

    In so einem Fall können sich mehrere verschiedene Tabellen anbieten. Eine Alternative können aber auch verschiedene VIEWs sein. Der Vorteil von VIEWs ist die vollständig sprachunabhängige Datenhaltung.

    Und warum ist das so? Weil für ein PK automatisch ein Index angelegt wird. Du verwechselst Ursache und Wirkung.

    Ja! Und? Ein kombinierter PK aus Person_ID und Nationalität ermöglicht es jede Person mit jeder Nationalität genau einmal zu verknüpfen. Nichts würde technisch dagegen sprechen eine Person mit über 200 Nationalitäten zu verknüpfen. Darüber hinaus gehende Einschränkungen müsstest du so oder so in deinem Programm oder in der Datenbank per TRIGGER/Constraint absichern.

    Du benötigst den PK aus Nationalität. Aber nach welchem Grundsatz muss es sich dabei um eine künstliche ID handeln?

    Ich weiß ja nicht wer so etwas behauptet. Standard ist, dass der Schlüssel einer Verknüpfungsrelation aus den den vollständigen Schlüsseln der verknüpften Relationen gebildet wird.

    In deinem Fall wäre es mit zusätzlicher ID möglich eine Person mehrfach mit der Nationalität deutsch zu verknüpfen.

    Ich fürchte du hast das Konzept der Beziehungen falsch verstanden. Fremdschlüssel zum Beispiel gehören streng genommen nicht zum Datenbestand sondern zu den Metadaten und drücken eine 1:n Beziehung aus. Legst du auf den FK zusätzlich noch ein UNIQUE-Constraint wird daraus automatisch eine 1:1 Beziehung. Solche Informationen lassen sich für gewöhnlich aus dem Schema heraus lesen. Wenn dein Schema allerdings fehlerhaft ist lässt sich das aufgrund der nicht dokumentierten Beziehungen nicht feststellen.

    MySQL kann zwar einige Dinge nicht oder nur schlecht. Aber so schlecht ist MySQL dann auch wieder nicht. Wenn so gearbeitet wird ist das entweder schlechter Stil oder ein Mangel an Datenbankkenntnissen. Ein gutes Design ermöglicht es die gewünschten Informationen in passender Form abzufragen.
     
  5. Sophus

    Sophus Datenbank-Guru

    In der neuen "Version" habe ich einiges Berücksichtigt. Wäre das soweit in Ordnung? Oder wäre da auch noch weiteres anzumerken?
     
  6. Hony%

    Hony% Datenbank-Guru

    Konkret würde ich persönlich auf die ID in den Relationen Geschlecht und Nationalität verzichten. Auch würde ich Person_ID und Nationalität(_ID) als zusammengesetzten PK kennzeichnen.
     
  7. Sophus

    Sophus Datenbank-Guru

    Ich bin verwirrt. Wieso verzichtest du bei der Tabelle Nationalität auf ein ID-Feld? Arbeitest du nicht gerne mit IDs? Oder machst du es an möglichen Datensatz-Mengen abhängig?

    Und zu der Zusammensetzung der IDs aus Nationalität und Person. Ich hoffe mal sehr stark, dass du dich dabei auf die Zwischentabelle Nationalität_Person beziehst. Denn in der Tabelle Person wäre es mit befremdlich. Wenn du dich also auf die besagte Zwischentabelle beziehst, dann wäre die ID in der Zwischentabelle, also Nationalität_Person_ID so etwas wie eine zusammengesetzte ID, denn unter dieser ID wären Person_ID und National_ID vereint.
     
  8. Hony%

    Hony% Datenbank-Guru

    Ich setzte IDs grundsätzlich nur dann ein wenn sie notwendig sind um ein Tupel eindeutig zu halten und wenn dies nicht oder nur unzureichend mit anderen Möglichkeiten umsetzbar ist.

    Frage dich einfach selbst: Welchen Mehrwert bietet mir in den beiden Relationen eine ID? Und vergiss dabei bitte nicht, dass du dadurch mit zusätzlichen UNIQE-Constraints arbeiten musst.

    Genau das. ;)

    Nationalität_Person=(Person_ID, Nationalität)

    Ein Primärschlüssel besteht nicht zwingend nur aus einem einzigen Attribut.
     
  9. Sophus

    Sophus Datenbank-Guru

    IDs bieten mir IMMER und GRUNDSÄTZLICH bei Abfragen einen riesigen Vorteil. Wieso also soll ich in meiner Abfrage nach Inhalten eines Feldes suchen, wenn ich doch wunderbar mit IDs arbeiten kann?

    Sprich, du willst in der Zwischentabelle Nationalität_Person aus dem Feld Nationalität_Person_ID nun Person_ID machen? Jedoch existiert in der Tabelle Person bereits das Feld Person_ID.

    P.S. Ich bin kein Datenbank-Spezialist, und habe daher an einigen Stellen oftmals das Gefühl, dass du für meinen Geschmack zu hoch greifst. Zum Beispiel erwähnst du UNIQE-Constraint, und ich weiß nicht mal was das sein soll. Oder du sagst, dass ein Primärschlüssel nicht zwingend nur ein einziges Attribut besitzen muss, und ich weiß nicht mal konkret was das mir aussagen soll, weil mir hier ein Beispiel fehlt. Dies sind so einige Beispiele, wo ich merke, dass es mir weniger hilft, wenn du zu hoch greifst und vieles einfach voraussetzt. Immerhin will ich ja auch was abgewinnen, wenn ich hier was lese :)
     
  10. Hony%

    Hony% Datenbank-Guru

    Der wäre? Geschwindigkeit zählt nicht, da diese durch den Index beeinflusst wird.

    Daran ändert sich ja nichts.

    Zwischen den Relationen Person und Nationalität besteht eine n:m Beziehung. Eine solche wird durch eine Verknüpfungsrelation abgebildet. Das hast du mit der Relation Nationalität_Person gemacht. In deinem Diagramm kennzeichnest du jetzt Person_ID und Nationalität_ID einzeln als FK. Soweit ist das auch richtig. Allerdings bilden beide Attribute zusammen den PK der Relation. Das nennt man dann zusammengesetzten Primärschlüssel. Und diesen Sachverhalt hast du in deinem Diagramm nicht abgebildet.

    In deiner aktuellen Version besitzt jede Nationalität eine eindeutige (unique) ID. Das verhindert allerdings nicht, dass du zum Beispiel die Nationalität deutsch mehrfach unter verschiedenen IDs anlegst. Um das zu verhindern müsstest du das Attribut Nationalität ebenfalls als eindeutig deklarieren. Und das nennt sich UNIQE-Constraint.

    Das Beispiel hatte ich ja mitgeliefert:

    Nationalität_Person=(Person_ID, Nationalität)

    Ein Primärschlüssel (PK) besteht aus einem oder mehreren Attributen und ist innerhalb einer Relation/Tabelle immer einzigartig. In deiner ersten Version sähe die Relation so aus:

    Nationalität_Person=(Nationalität_Person_ID, Person_ID, Nationalität)

    Das bedeutet konkret, dass solange eine eindeutige ID benutzt wird jede beliebige Kombination von Person und Nationalität auch mehrfach erlaubt ist.

    Anderes falsches Beispiel:

    Nationalität_Person=(Person_ID, Nationalität)

    In diesem Fall würde man eine 1:n Beziehung abbilden, da jede Person nur ein einziges mal auftauchen darf. Damit wäre die Forderung nach mehreren möglichen Nationalitäten nicht erfüllt.

    Wenn ich jetzt zum Beispiel bis zu 3 Nationalitäten gewichtet abbilden will kann ich auch das durch die Datenbank absichern:

    Gewicht {primär, sekundär, tertiär} oder Gewicht {1, 2, 3}
    Nationalität_Person=(Person_ID, Nationalität, Gewicht) [UNIQE=(Person_ID, Gewicht)]

    Der Primärschlüssel der Relation bildet sich aus den Primärschlüsseln der referenzierten Relationen. Zusätzlich wird ein UNIQUE-Constraint über Person_ID und Gewicht definiert. Dadurch kann ich sicher stellen, dass es pro Person nur maximal 3 Nationalitäten gibt. Die Gewichtung selbst kann später auch verworfen werden falls sie nicht benötigt wird.

    Achtung!
    Das Gewicht ist in diesem Fall ein Hilfsattribut. Durch dieses Attribut wird lediglich sichergestellt, dass es nur maximal 3 Alternativen gibt.

    Sollst du ja auch. Da ich aber deinen Wissensstand nicht kenne ist es deine Aufgabe nachzufragen wenn du etwas nicht verstehst. Eine Erklärung ist dann leicht nachgeliefert.
     
  11. Sophus

    Sophus Datenbank-Guru

    Nun, wir sind hier noch bei Personen, die als Stammdaten angelegt werden. In meinem Programm werden die Datensätze der Personen über eine ListView ausgegeben. In dieser ListView (Ansicht in Detail) sind mehrere Spalten. An erster stelle im Spaltenkopf ist dann die ID-Spalte. Aber damit der Anwender sich nicht befassen muss, und die GUID sowieso sehr lang ist, wird diese Spalte vom Programm versteckt. Aber diese Spalte ist trotzdem vorhanden, nur eben nicht sichtbar. Sobald der Anwender einen Doppelklick auf einen bestimmten Eintrag in der ListView betätigt, wird in Windeseile mit dieser ID aus dem ersten Spaltenkopf gearbeitet, und nicht mit dem Vorname oder Nachnamen der Person. Warum auch? Es gibt viele Julias, viele Brads, viele Georges etwas.

    Nun, in der Zwischentabelle/Verknüpfungstabelle Nationalität_Person gab es doch die zusammengesetzte ID mit der Bezeichnung Nationalität_Person_ID. In dieser ID werden dann Person_ID und Nationalität_ID untergebracht.

    So habe ich früher immer gearbeitet. Aber dabei merkte ich, dass ich mir dadurch mehr Arbeit aufgebunden habe, als nötig. Immer musste mein Programm beim Speicher-Vorgang darauf achten ob ein Fehler stattfindet, und wenn ja, muss diese abgefangen werden. Seitdem habe ich mir gedacht, dass es nicht meine Aufgabe als Entwickler ist, darauf zu achten, dass der Anwender seine Datenbank sauber pflegt, sondern dass der Anwender sich darum kümmern muss. Um dieses Problem entgegen zu kommen, baue ich eine kleine Like-Operation in meinem Programm an. Das heißt, im Vorfeld bekommt der Anwender ein kleines Fenster, in der er den Namen der Person eingeben soll. Mit einem Enter findet eine kleine Suche statt. Findet mein Programm was, bekommt der Anwender nur eine kleine Meldung a la "Hey, die Person Julia Roberts" gibt es in deiner Datenbank, möchtest du sie trotzdem hinzufügen?". Warum auch immer der Anwender eine zweite Julia hinzufügen möchte, sei mal dahingestellt, jedoch gewähre ich ihm die Option, und verbiete da nichts, so nach dem Motto "So, da ist schon ein Datensatz Julia Roberts, also wird nichts hinzugefügt, weil ich das so sage und so will, denn ich passe hier auf, dass nichts doppelt vorkommt." Wie gesagt, ich habe mich seit Jahren davon abgewendet, darauf aufzupassen. Die Verantwortung und Pflicht liegt allein beim Anwender. Er soll nur eine kurze Meldung bzw. einen kurzen Hinweis bekommen.

    Wie bereit oben erwähnt, möchte ich nicht überwachen, dass eine Person auch nur drei Nationalitäten bekommt. Die Tatsache allein, dass eine Person mehrere Nationalitäten bekommen kann, war für mich ausreichend genug, eine Zwischentabelle anzulegen. Wenn ein Anwender meint, einer Person 3154813649841 Nationalitäten anzulegen, soll er es machen. Er ist allein für die Pflege seiner Datenbank verantwortlich. Und wenn ich eine kleine "Kontrolle" einbauen möchte, geht dies auf der Seite der Software sehr einfach. Dazu muss ich in der Datenbank nichts begrenzen.

    Also kann meine ID Nationalität_Person_ID unter diesen Bedingungen wieder zurück? Denn nach deiner Berücksichtigung hatte ich sie ja raus genommen.

    Mir fällt nur auf, dass ich in vielerlei kein Datenbank-Spezialist bin. Zum Beispiel heißt bei mit Attribut einfach nur Felder. Daher habe ich nicht verstanden, als du meintest, dass ein PK nicht nur zwingend ein Attribut haben muss. Jetzt weiß ich, dass du Felder meinst. Genauso schreibst du die ganze Zeit von Relationen. Nun ist mir klar, dass du von Tabellen redest. Nun wird mir einiges klarer.
     
  12. Hony%

    Hony% Datenbank-Guru

    Richtig. Gerade bei Personen ist es schwierig einen eindeutigen Schlüssel zu definieren. Gegen diese ID habe ich auch nie etwas gesagt. Allerdings wird es wohl kaum unvorhersehbar viele Geschlechter »männlich« geben. ;)

    Darunter versteht man aber keinen zusammengesetzten Primärschlüssel. Dabei handelt es sich nur um einen künstlichen Schlüssel der aus zwei anderen Attributen zusammengefügt wird. Streng genommen verstößt eine solche Konstruktion auch noch gegen die 1. Normalform.

    So wird ein zusammengesetzter Primärschlüssel in SQL definiert:
    Code:
    CREATE TABLE Nationalität_Person
    (
        Person_ID BIGINT NOT NULL,
        Nationalität VARCHAR(50) NOT NULL,
        PRIMARY KEY(Person_ID, Nationalität)
    )
    
    In dem Fall sind Einschränkungen natürlich eher lästig als hilfreich. Allerdings benötigt deine Anwendung dazu mehrere Abfragen während die Datenbank das auf einen Rutsch erledigen kann. Bei einer Einzelplatzanwendung spielt das keine Rolle. In großen Mehrbenutzerumgebungen lässt sich der Unterschied in der Anzahl der benötigten Server messen.

    Klar. Wenn du die Datenbank nur als Datengrab benutzen willst. ;)

    Die Bezeichnungen werden gerne synonym verwendet obwohl es semantische Unterschiede gibt. Das soll jetzt aber keine Rolle spielen.
     
  13. Sophus

    Sophus Datenbank-Guru

    Wenn ich deinen SQL-Statement richtig verstanden habe, legst du eine Tabelle mit dem Namen Nationalität_Person an. Darin erstellst du zwei Felder/Attribute mit den Namen Person_ID und Nationalität. Diese beiden Felder/Attribute machst du dann zum Primärschlüssel, richtig? Was aber, wenn ich in der Tabelle Nationalität dennoch weiterhin mit dem ID-Feld arbeiten will? Nach meiner Login sähe das wie folgt:

    Code:
    CREATE TABLE Nationalität_Person
    (
        Person_ID BIGINT NOT NULL,
        Nationalität_ID BIGINT NOT NULL,
        PRIMARY KEY(Person_ID, Nationalität_ID)
    )
    
    Was ist ein Datengrab? Nie gehört diesen Ausdruck.

    Gruß
    Sophus
     
  14. Hony%

    Hony% Datenbank-Guru

    Richtig. Wenn du die ID beibehalten willst sähe die Definition so aus.

    Datengrab ist ein süffisanter Ausdruck um deutlich zu machen, dass du die Datenbank nicht als Datenbank sondern nur als Ablagestelle benutzen willst. Für deine Zwecke reichte auch eine Textdatei oder ein Zettelkasten.
     
  15. Sophus

    Sophus Datenbank-Guru

    Na ja, wie ich einleitend erklärt habe, wird die Struktur noch komplexer. Ich wollte nur mit der Person anfangen. Demzufolge wäre eine Textdatei einfach überfordert. Es ist schon richtig, dass meine Anwendung mit einer Datenbank arbeitet :)
     
Die Seite wird geladen...

Diese Seite empfehlen

  1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies.
    Information ausblenden