Zum Inhalt
wannacode

Beziehungstypen: 1:1, 1:N, M:N

Kurz gesagt: Eine Beziehung zwischen zwei Tabellen ist eins-zu-eins, eins-zu-viele oder viele-zu-viele. Ihr Typ entscheidet, wo der Fremdschlüssel hingehört und wann du eine Verbindungstabelle brauchst.

Problem

Eine Karte und Tags

Der Shop führt zwei neue Dinge ein. Das erste ist eine Kundenkarte: Jeder Kunde kann eine Karte mit Punkten haben. Das zweite sind Produkt-Tags wie „vegan“, „glutenfrei“ und „bio“, damit die Website danach filtern kann.

Wo speicherst du sie? Eine Spalte card_number in customers? Eine Spalte tags in products mit dem Text „vegan, bio“? Die Antwort hängt von einer Frage ab: Wie viele Dinge auf der einen Seite gehören zu wie vielen auf der anderen?

Die Idee

Eins zu viele (1:N)

Ein Kunde hat viele Bestellungen. Jede Bestellung gehört zu einem Kunden. Das ist eine Eins-zu-viele-Beziehung, geschrieben 1:N.

Der Schlüssel gehört auf die „viele“-Seite. Jede Bestellung sagt mit customer_id, wem sie gehört:

customers

  • PKidinteger
  • nametext *
  • emailtext *
  • citytext
  • joined_attext *

orders

  • PKidinteger
  • FKcustomer_idinteger *→ customers
  • ordered_attext *
  • statustext *

Andersherum geht es nicht. Wie viele Spalten order_1, order_2 sollte ein Kunde haben? Maria hat 12 Bestellungen, und morgen hat sie 13.

SQLDatenbank: Shop

Das ist die häufigste Beziehung. Im Shop sind auch eine Kategorie und ihre Produkte so verbunden, ebenso ein Produkt und seine Bewertungen.

Probier es aus

Produkte nach Kategorie

Wie viele Produkte hat jede Kategorie, die Produkte hat? Zeige den Namen der Kategorie und die Anzahl.

SQLDatenbank: Shop

Die Idee

Eins zu eins (1:1)

Jeder Kunde hat höchstens eine Karte, und jede Karte gehört zu einem Kunden. Das ist Eins-zu-eins, 1:1. Du speicherst es wie 1:N, mit einem Schlüssel zum Kunden, plus einer weiteren Regel: UNIQUE.

loyalty_cards

  • PKidinteger
  • FKcustomer_idinteger *→ customers
  • numbertext *
  • pointsinteger *
  • issued_attext *
SQLDatenbank: Shop

Fünf Kunden haben eine Karte. Versuch, Maria eine zweite zu geben:

SQLDatenbank: Shop

UNIQUE auf customer_id lässt keine zweite Zeile für denselben Kunden zu. Ohne es wäre die Beziehung 1:N.

Warum nicht einfach Spalten in customers? Das geht auch. Oft sind 1:1 einfach mehr Spalten in derselben Tabelle. Eine eigene Tabelle lohnt sich, wenn die meisten Zeilen den zweiten Teil nicht haben (15 der 20 Kunden haben keine Karte und hätten leere Zellen) oder wenn er ein Eigenleben hat: Die Karte geht verloren, wird ersetzt, hat eigene Punkte.

Probier es aus

Wer hat noch keine Karte

Das Marketing will jedem Kunden eine Karte anbieten, der noch keine hat. Zeige ihre Namen.

SQLDatenbank: Shop

Die Idee

Viele zu viele (M:N)

Eine Bestellung hat viele Produkte. Ein Produkt steckt in vielen Bestellungen. Das ist Viele-zu-viele, M:N.

Hier kann der Schlüssel in keine der beiden Tabellen. Die Lösung ist eine dritte Tabelle, eine Verbindungstabelle, mit einer Zeile für jedes Paar. Im Shop ist das order_items: Jede Zeile ist ein Produkt in einer Bestellung, mit Menge und Preis.

products

  • PKidinteger
  • nametext *
  • FKcategory_idinteger→ categories
  • pricereal *
  • stockinteger *
  • added_attext *

order_items

  • PKorder_idinteger→ orders
  • PKproduct_idinteger→ products
  • quantityinteger *
  • unit_pricereal *

In welchen Bestellungen steckt der Kaffee (Produkt 17)?

SQLDatenbank: Shop

Mit Tags ist es dasselbe. Ein Produkt hat viele Tags, und ein Tag hängt an vielen Produkten:

tags

  • PKidinteger
  • nametext *

product_tags

  • PKproduct_idinteger→ products
  • PKtag_idinteger→ tags
SQLDatenbank: Shop

Sieh es dir an

Das Paar ist der Schlüssel

Der Primärschlüssel von order_items ist das Paar (order_id, product_id). Versuch, das Brot ein zweites Mal zu Bestellung 60 hinzuzufügen, in der es schon ist:

SQLDatenbank: Shop

Die Datenbank erlaubt dasselbe Paar nicht zweimal. Ein Produkt steckt einmal in der Bestellung, und mehr Stücke kommen in quantity. Sonst würde die Auswertung „wie oft wurde das Brot bestellt“ dasselbe Produkt aus einer Bestellung doppelt zählen.

1. Jedes Produkt hat genau eine Kategorie, und eine Kategorie hat viele Produkte. Wo gehört der Schlüssel hin?

Probier es aus

Tags auf der Website

Neben jedem Tag zeigt die Website, wie viele Produkte ihn haben. Zeige den Namen des Tags und die Anzahl.

SQLDatenbank: Shop

Übung

Zwei Aufgaben

1. Die Seite der Äpfel zeigt ihre Tags. Welche sind es?

Die Tags des Produkts „Äpfel“:

SQLDatenbank: Shop

2. Ein Kunde sucht Produkte, die vegan und glutenfrei sind. Zeige ihre Namen.

Die Produkte mit beiden Tags, „vegan“ und „glutenfrei“:

SQLDatenbank: Shop

Test

Teste dich

1. Was macht die Beziehung zwischen loyalty_cards und customers zu 1:1 statt 1:N?
2. Ein Student belegt viele Kurse, und ein Kurs hat viele Studenten. Wie speicherst du das?
3. Warum ist der Primärschlüssel von product_tags (product_id, tag_id)?
4. Warum findet die Abfrage mit WHERE t.name = 'vegan' AND t.name = 'glutenfrei' nichts?

Erstellt von Ivo Gergov im Rahmen der Kampagne von Evo Tech für zugängliche Programmierausbildung ·