Wie mit Verknüpfungen umgehen?

Tommy57

Erfahrenes Mitglied
Hallo,

ich baue gerade eine Datenbank für Fussballer und frage mich, ob das so gut ist?

continent
id, name

country
id, name, continent_id

league
id, name, continent_id, country_id

team
id, name, continent_id, country_id, league_id

player
id, name, continent_id, country_id, league_id, team_id


Ich frage mich, ob man alle Relationen in jede Tabelle packt. Also vom Speicher her ist das kein Problem und ich sehe aktuell den Vorteil, dass ich z.B. nach allen Spielern eines Kontinentes suchen kann. Sonst müsste ich ja glaube ich einen Umweg über vier Tabellen machen. Andererseits ist glaube ich die Gefahr auf inkonsistente Daten um einiges höher.
Kann man der Datenbank irgendwie die Relation erklären, so dass sie eine Fehlermeldung ausspucken würde, wenn ich bei einem Insert einem Spieler zu seiner country_id die falsche continent_id liefern würde? Ich nutze MySQL und die Tabellen sind InnoDB.

Gruß, Tommy
 
Edit: Sry falsch gelesen. Text entfernt.

Edit2: Ev. könnte man die Prüfung mittels trigger steuern. (weiß jetzt nicht ganz ob mySql das unterstützt, aber glaube schon)
 
Zuletzt bearbeitet:
Hi Spyke,

danke für die Antwort.

Mit nem Trigger müsste es gehen. Dann könnte ich auch noch einstellen, dass wenn sich z.B. der Kontinent einer Region ändert, sich dieser dann auch in allen anderen Tabellen mitändert. Müsste ich mal drüber nachdenken. Und schauen, ob das mit MySQL überhaupt geht.

Ich hatte mal gelesen, dass diese Verknüpfungen ein Vorteil von InnoDB sind. Deswegen hatte ich mich gefragt^^


Ich habe mich jetzt entschieden, beim Spieler Liga, Land und Kontinent weg zu lassen. Die Abfragen würde ich dann immer über die Team-Tabelle machen und dann mit den Spielern joinen.

Kann mir vllt jemand ein Tutorial oder ähnliches empfehlen, wo ich mich in professionelle Datenbank Architektur einlesen kann. :)
 
Zuletzt bearbeitet:
Du könntet auch einfach ein Frontend bauen, in dem Du zuerst den Kontinent, dann die darin befindlichen Länder, darin die befindlichen Ligen und dann die Teams auswählst.
So kannst Du die jeweils referenzierende id mitgeben und hast immer konsistente Daten.
 
Hi Fragenfrager,

das ist im Frontend unter Anderem auch so gedacht. Nur es wird auf der Seite auch andere Gruppierungen geben. Deswegen nutze ich Indices und möchte inkonsistente Daten vermeiden.
 
Du kennst aber schon die Normalformen: http://de.wikipedia.org/wiki/Normalisierung_(Datenbank)
Zudem solltest du dir Fremdschlüssel (oder auch Foreign Keys) angucken. Dann meckert die Datenbank auch, wenn du ******e bei den Beziehungen zwischen den Tabellen baust.
Die jeweilige Angabe der continent_id kannst du dir in jedem Fall sparen, die kann ja direkt über der Kontineent kann ja direkt über die country_id bestimmt werden.
 
Hi alxy,

ich versteh nicht ganz, was du mit Normalform meinst? Meine Tabellen beinhalten keine redundanten Texte, halt nur die Fremdschlüssel, die ich zur Indexierung brauche, außerdem spare ich mir sowas wie "WHERE country_id IN (...)".

Also nach meinem Kenntnisstand sind die Tabellen alle normalisiert. Die Frage ist, ob etwas gegen die redundanten Fremdschlüssel spricht, und wenn nicht, ob man diese mit einem einfach Befehl vernetzen kann. Hatte sowas mal gelesen, dass InnoDB das kann.
 
Meinst du JOIN Abfragen tommy?

Ansonsten fand ich die Idee gut beim Spieler Liga, Land und kontintent wegzulassen.
Da sollte es eher eine beziehungstabelle zwischen dem team und spieler geben.
Dies sollte dann alles leicht mittels JOIN etc. händelbar sein.

Mit verwendung von foreignkeys und constraints (und transaction) sollte es auch kaum (keine) inkonsistenten daten geben.
 
InnoDB ist die freie MySQL-Engine, mit der man Relationen mittels Foreign Keys aufbauen kann. Was du Fremdschlüssel nennst, sind Foreign Keys. Wenn man einen echten Fremdschlüssel aufbaut, also mittels

Code:
CREATE TABLE `tabelle1` (
  `id_in_tabelle1` INT NOT NULL AUTO_INCREMENT,
  `wert1` VARCHAR(100),
  `id_irgendwas` INT NOT NULL DEFAULT 0,
  PRIMARY KEY(`id_in_tabelle1`)
);

CREATE TABLE `tabelle2` (
  `id_in_tabelle2` INT NOT NULL AUTO_INCREMENT,
  `wert1` VARCHAR(10) NOT NULL DEFAULT '',
  PRIMARY KEY(`id_in_tabelle2`)
);

ALTER TABLE
  `tabelle1`
ADD CONSTRAINT `fk_Fremdschluessel`
FOREIGN KEY (`id_irgendwas`) REFERENCES `tabelle2` (`id_in_tabelle2`)
ON DELETE CASCADE
ON UPDATE SET NULL;

Das bedeutet, tabelle1 hat eine Spalte 'id_irgendwas', die einen Fremdschlüssel auf 'tabelle2' enthält.

Wenn jetzt in 'tabelle2' ein Datensatz gelöscht wird, wird der Datensatz in 'tabelle1' auch gelöscht, der auf den Datensatz in 'tabelle2' zeigt.

Wenn die 'id_in_tabelle2' geändert wird, auf die in 'tabelle1' referenziert wird, wird der Fremdschlüssel in 'tabelle1' auf 0 gesetzt.

Das mit den Transaktionen ist zudem eine bewährte Methode, damit es keine Kreuz-Updates geben kann. Dafür sollte man sich allerdings eine Art Transaktionsmanager bauen, mit dem solche Race-Conditions (simultane Updates der gleichen Daten) behandelt werden.
 
@Spyke:
Ich würde beim Spieler die aktuelle Mannschaft speichern, um immer schnell an die aktiven Spieler einer Mannschaft zu kommen. Es wird aber eine Assoziationstabellen geben, in der Spieler zu Mannschaft verknüpft wird, da ja auch ein Spieler bei verschiendenen Mannschaften gespielt haben kann, bzw auch spielt (Team und Nationalmannschaft oder Spieler und Co-Trainer).

Ist echt kompliziert das Fussballsystem mit einer Datenbank abzubilden. Gibt echt viele Faktoren, die berücksichtigt werden müssen.


@saftmeister:
Super, genau das habe ich gesucht. Danke. Spricht was dagegen einen Foreign-Key zu mehreren Tabellen zu haben?

SQL:
ALTER TABLE `continent`ADD CONSTRAINT `fk_continent_country`
FOREIGN KEY (`id`) REFERENCES `country` (`continent_id`)
ON DELETE CASCADE
ON UPDATE SET NULL;

ALTER TABLE `continent`ADD CONSTRAINT `fk_continent_league`
FOREIGN KEY (`id`) REFERENCES `league` (`continent_id`)
ON DELETE CASCADE
ON UPDATE SET NULL;

...

EDIT: Wie macht man eigentlich den MySQL Code-Block hier? Ich schreibe immer "SQL", dann ist das Highlighting aber meist nicht so toll.
 
Zuletzt bearbeitet von einem Moderator:

Neue Beiträge

Zurück