Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

birdfreeyahoo

Alter Hase

  • »birdfreeyahoo« ist der Autor dieses Themas

Beiträge: 756

Wohnort: Schorndorf

Beruf: Junior Software Engineer

  • Private Nachricht senden

1

22.11.2015, 04:17

SQL Datenbank mehrfache Beziehung

Hallo, ich arbeite gerade an einem Projekt, in dem ich SQLite-Datenbank in Android verwende.
Ich kenne mich schon ein wenig mit Datenbanken aus, habe aber eine Frage:

Angenommen ich habe eine Tabelle mit Lehrern. Jeder hat eine ID und sonstige Attribute. Dann habe ich noch eine Tabelle aus Schülern mit ID und sonstigen Attributen.
Jetzt soll ein Lehrer mehrere Schüler unterrichten und ich will diese Relation speichern. Wie tue ich das?

Ich habe mir überlegt eine extra Tabelle zu erstellen, wo immer einem Lehrer ein Schüler zugeordnet wird (per ID).

2

22.11.2015, 05:32

Das wäre aber nicht zwingend korrekt.
Natürlich hat ein Schüler mehrere Lehrer. Selbst wenn dem nicht so ist und es um Klassenlehrer geht: ich würde das nicht beschränken, indem ich in die Schüler-Tabelle einfach ne Lehrer-id speichere.
Bei sowas würde ich beide sogar eher in Gruppen stecken und untereinander garkeine direkte Zuordnung geben (sondern beide belongsTo group/class). Aber das kommt eh aufs Bedürfnis an.

Gängig ist eine Tabelle, welche nur die Zuordnungen beinhaltet:

lehrer
id
...

schueler
id
...

lehrer_schueler
(id)
lehrer_id
schueler_id

Schüler eines Lehrers abfragen z.B.:
SELECT schueler.* FROM lehrer_schueler, schueler WHERE lehrer_schueler.lehrer_id = #some_id# AND lehrer_schueler.schueler_id = schueler.id
Entsprechend umgekehrt möglich.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »ventrix« (22.11.2015, 05:39)


dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

3

22.11.2015, 05:35

Richtig, die Relation "y unterrichted x" bzw. "x wird von y unterrichted" sollte in einer eigenen Tabelle dargestellt werden. Im konkreten Fall würde man für diese Tabelle unter Umständen dann einen Composite Primary Key aus Schüler und Lehrer ID in Erwägung ziehen...

4

22.11.2015, 12:26

Also wen du den Fall hast das ein Lehrer mehrer Schüler und mehrere Schüler meherer Leher hat, dann würde man von einer m zu m Beziehung sprechen.(viele zu viele)
diesen Fall löst man in der Regel über eine Zwischentabelle.

Falls du aber nur den Fall hast das ein Leherer mehere Schüller hat dann würde man von einer 1 zu m Beziehnung sprechen.
Du würdest in diesem Fall ein Verweis in der Schülertabelle zum ensprechenden Leherer eintragen(Foreign key)

Hoffe ich konnte helfen
Grüsse blubb

5

22.11.2015, 12:29

Um noch ein paar Fachbegriffe reinzubringen:

Wenn das hier zutrifft:

Ein Lehrer - > mehrere Schüler
Ein Schüler -> mehrere Lehrer

Dann hast du eine "m zu n" - Beziehung, die in eine eigene Tabelle muß (m Lehrer zu n Schülern).

Wenn du nur sowas hier hast:
Ein Lehrer -> mehrere Schüler
ist es eine "1 zu m" - Beziehung. Die kann aufgelöst werden indem du in der Schüler-Tabelle einen Fremdschlüssel auf die Lehrer-Tabelle einbaust.
Empires in Space
MMO 4X, Rundenbasiert
HTML5/TypeScript/Javascript/CSS/C#/SQL

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

6

22.11.2015, 13:47

Es wurde ja bereits darauf hingewiesen, dass es sich wahrscheinlich um eine m-zu-n Beziehung handelt (und auch, dass man bei einer entsprechenden Zwischentabelle die Fremdschlüssel als zusammengesetzten Primärschlüssel verwenden könnte).

Allerdings solltest du dir erstmal Gedanken machen, ob dein Modell so auch vollständig ist.
Unterrichtet ein Lehrer einzelne Schüler, oder unterrichtet er mehrere, in eine Klasse/einen Kurs/... zusammengelegte Schüler? Da das Beispiel "Lehrer" und "Schüler" umfasst, würde ich Klassen als sehr wahrscheinlich ansehen. Diese würden dann wiederum aus mehreren Schülern bestehen und von Lehrern unterrichtet werden, während Lehrer mehrere Klassen unterrichten.
Was wird unterrichtet? Abhängig davon, was für deine Anwendung relevant ist, könnte das noch eine relevante Information sein. Da es sich weder um eine reine Information über den Lehrer (Lehrer können meist mehrere Fächer unterrichten), noch über die Klasse (Klassen können Unterricht in mehreren Fächern erhalten) handelt, ist es eine Eigenschaft der Beziehung und müsste in der Zwischentabelle vermerkt werden.
Beim letzten Punkt bin ich davon ausgegangen, dass die Schüler in "Klassen" zusammengefasst werden, welche in mehreren Fächern unterrichtet werden. Es könnte aber auch sein, dass stattdessen "Kurse" erstellt werden, welche bereits den Unterricht in genau einem bestimmten Fach (ggf. bei einem bestimmten Lehrer) implizieren, wo die Information über den Inhalt des Unterrichts wieder eine Eigenschaft des Kurses wäre.

Mal angenommen, jeder Schüler hätte tatsächlich nur einen Lehrer. Es wurde bereits geschrieben, dass eine solche 1-zu-n Beziehung realisiert werden kann, indem die n-Element-Tabelle (Schüler) um einen Fremdschlüssel erweitert wird. Allerdings gehören zu dieser Beziehung eventuell noch weitere Eigenschaften, wie das Fach, der Termin inklusive Raum etc. Diese Eigenschaften könnten natürlich dem Schüler zugewiesen werden, da über ihn die Beziehung realisiert wird.
Das Problem dabei ist jedoch, dass entweder bestimmte Eigenschaften der Beziehung erforderlich sind _und_ die Beziehung vorhanden sein müssen, oder dass die Beziehung optional ist, ohne dass Eigenschaften der Beziehung erforderlich sein können. Mit etwas komplizierteren Constraints kann man ein solches Verhalten hinbekommen, einfacher wäre es aber immernoch eine Zwischentabelle anzulegen, bei der der Fremdschlüssel zum Schüler einmalig oder gar der Primärschlüssel der Tabelle ist. So kann die Beziehung optional sein _und_ Pflichtfelder beinhalten.
Ein weiterer Vorteil einer solchen Umsetzung ist, dass es einfacher ist, die Beziehung in eine m-zu-n Beziehung abzuwandeln. Die Einmaligkeit des Schüler Fremdschlüssels müsste nur in eine Einmaligkeit der Kombination Schüler<->Lehrer umgewandelt werden.
Ein anderes Beispiel wären Adressen in einem Online-shop. Man geht vielleicht davon aus, dass ein Benutzer eine eigene Adresse hat, die er ggf. ändern kann, dennoch wäre es von Vorteil, wenn der Benutzer diese bspw. nicht von Anfang an eingeben muss, man aber dennoch die Prüfungen hätte -> separate Tabelle für Adressen, die eine Referenz auf den Benutzer besitzen. Stellt sich später heraus, dass die Benutzer häufiger unterschiedliche Adressen verwenden (bspw. wenn die Rechnungsadresse sich häufiger von der Lieferadresse unterscheidet) und dass es komfortabel wäre, wenn sie diese ebenfalls alle speichern könnten, dann wäre es einfacher, einfach mehrere Einträge in bereits besagter Tabelle zuzulassen (Einmaligkeit des Benutzer-Fremdschlüssels entfernen). Amazon beispielsweise erlaubt es einem, mehrere Adressen zu verwalten.
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

birdfreeyahoo

Alter Hase

  • »birdfreeyahoo« ist der Autor dieses Themas

Beiträge: 756

Wohnort: Schorndorf

Beruf: Junior Software Engineer

  • Private Nachricht senden

7

22.11.2015, 15:06

Ja, es ist eine m zu n Beziehung deshalb fällt der Schlüssel beim Schüler raus.
Es war nur beispielhaft, da ich in meinem Fall noch in der Modellierung bin und das beim Planen der Tabellen gerne wüsste, wie man sowas am besten löst.
Composite Primary Attribute heißt dann sowas wie "Objekt ist gleich wenn Schüler & Lehrer-ID gleich sind"?

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

8

22.11.2015, 23:43

Ein zusamengesetzter Primärschlüssel (Composite Primary Key) besteht im Gegensatz zu einem normalen Primärschlüssel nicht aus einem einzigen Wert, sondern aus mehreren. Um bspw. einen ganz bestimmten Datensatz abzurufen, muss man auch da den gesamten Primärschlüssel angeben, welcher eben aus mehreren Werten besteht.
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

birdfreeyahoo

Alter Hase

  • »birdfreeyahoo« ist der Autor dieses Themas

Beiträge: 756

Wohnort: Schorndorf

Beruf: Junior Software Engineer

  • Private Nachricht senden

9

26.11.2015, 19:05

Ok danke erstmal für die Antworten, das hat mir schonmal weitergeholfen.
Jetzt habe ich meine Datenbank (fürs erste) entwickelt, aber ich glaube irgendwas kann ich besser machen. Es sieht folgendermaßen aus:

Es gibt verschiedene Orte (meistens Räume) die in der Locations-Table gespeichert sind

_ID (INT PRIMARY KEY) | LocationName (TEXT) | Type (TEXT)

Desweiteren können Räume von Personen bewohnt werden (m*n) und Funktionen haben (m*n), also 2 Tables mehr

_ID (INT PRIMARY KEY) | PersonName (TEXT)

und

_ID (INT PRIMARY KEY) | FunctionName (TEXT)

und die Relationstabellen:

LocationID (INT) | PersonID (INT)

LocationID (INT) | FunctionID (INT)


Damit habe ich 5 Tabellen die 3 Entitäten repräsentieren die in einer m*n-Beziehung zueinander stehen.

Jetzt kann ein User suchen, nach Location, Person und Function und ich weiß nicht nach was er sucht ich hab nur den query string.
Jetzt will ich von meinem ContentProvider etwas zurückliefern (wie eine Tabelle). Wenn er direkt nach der Location sucht, reicht es ihm nur die Räume als Suchvorschlag zu geben. Wenn er nach Personen sucht, den Raum mit dieser Person im Suchvorschlag (als Text, es geht indirekt immer darum einen Raum zu finden).

Ich kann keine Fallunterscheidung machen, somit habe ich beschlossen, dass es in meinem Rückgabeformat 3 Spalten gibt nämlich LocationName, PersonName, und FunctionName.

Um jetzt die passenden Zeilen zu finden habe ich folgende, sehr unnötig kompliziert aussehende Anweisung konstruiert:

C-/C++-Quelltext

1
2
3
4
SELECT LocationName, PersonName, FunctionName
FROM Locations INNER JOIN Persons INNER JOIN Functions INNER JOIN PersonLocationRelations INNER JOIN FunctionLocationRelations
ON Locations._ID = PersonLocationRelations.LocationID AND PersonID = Persons._ID AND Locations._ID = FunctionLocationRelations.LocationID AND FunctionID = Functions._ID
WHERE LocationName LIKE QUERY OR PersonName LIKE QUERY OR FunctionName LIKE QUERY


Damit habe ich dann alle möglichen Kombinationen aus Location, Person und Function, in denen eines dieser enthalten ist, die als Teilstring den Query enthält.
Ich hab das Gefühl das kann ich irgendwie besser machen, optimal wäre, dass die unverwendete Spalte 0 ist, also wenn eine Location einen LIKE-Match liefert sind Person und Function NULL,
wenn eine Person gematcht wurde (also der User nach Person gesucht hat), ist Function NULL.

Ich hoffe jemand kann mir ein wenig helfen

mfg

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »birdfreeyahoo« (26.11.2015, 20:14)


Fireball

Alter Hase

Beiträge: 415

Wohnort: Werne

Beruf: Dipl. Inf.

  • Private Nachricht senden

10

27.11.2015, 12:59

Dir ist aber klar, dass du mit der Query eimal die ganze Datenbank umrührst oder?

Ich glaube ich hätte das etwas anders gemacht. Ein Lehrer (ggf. sogar viele - kann ja mal vorkommen, dass 2 Lehrer gleichzeitig unterrichten) und viele Schüler sind Teil einer Unterrichtseinheit. Diese Unterrichtseinheit findet in einem Raum statt. Über den Tag verteilt finden in dem Raum mehrere Unterrichtseinheiten statt. Damit sich nichts überschneidet könnte ein Trigger oder eine Prüfung durch dein Programm erfolgen.
Das Schüler immer vom selben Lehrer unterrichtet werden kommt glaube ich nicht ganz hin und wenn ja, dann wird er bestimmt nicht den ganzen Tag das gleiche mit den Schülern machen.

Schöne Grüße

Fb

Edit: Tipp von mir, zeichne eine Klassendiagramm und deren Beziehung, danach wandelst du das in ein Relationsmodell um oder noch besser du benutzt ein ORM Mapper, der diese lästige Arbeit für dich übernimmt.

Werbeanzeige