Zum Inhalt
wannacode

Constraints: Regeln für die Daten

Kurz gesagt: Constraints (NOT NULL, DEFAULT, UNIQUE, CHECK, PRIMARY KEY) sind Regeln im CREATE TABLE, mit denen die Datenbank selbst falsche Zeilen ablehnt.

Problem

Eine Tabelle, die alles nimmt

Hier ist eine Tabelle für die Lieferanten ganz ohne Regeln. Führ die Abfrage aus:

SQLleere Datenbank

Ein Lieferant ohne Namen ist hineingekommen. Dieselbe Umsatzsteuernummer kam zweimal hinein. Eine Bewertung von 7 auf einer Skala von 1 bis 5 kam hinein. Niemand hat geprüft.

Im Modul über das Ändern von Daten hat der Shop solche Zeilen mit Fehlern abgewiesen. Diese Fehler kommen von Regeln, die in CREATE TABLE stehen. Jetzt schreibst du sie.

Die Idee

NOT NULL und DEFAULT

Die Regeln stehen hinter dem Typ der Spalte. Sie heißen Constraints (Einschränkungen).

  • NOT NULL: Die Spalte darf nicht leer sein.
  • DEFAULT Wert: Was gespeichert wird, wenn der INSERT keinen Wert angibt.
SQLleere Datenbank

Die Molkerei hat „Sofia“ bekommen, weil ihre Stadt nicht angegeben war. Ein Lieferant ohne Namen kommt nicht hinein:

SQLleere Datenbank

DEFAULT CURRENT_DATE speichert das heutige Datum. Das ist praktisch für „wann es hinzugefügt wurde“:

SQLleere Datenbank

1 heißt „ja, es ist das heutige Datum“. Ersetze added_at = CURRENT_DATE durch added_at allein, und du siehst das Datum selbst.

Genauer, für Neugierige

CURRENT_DATE ist in SQLite das Datum in UTC, nicht in Ortszeit. In Bulgarien ist zwischen Mitternacht und 2 oder 3 Uhr morgens das Ortsdatum schon das neue, während UTC noch das alte hat. CURRENT_TIMESTAMP liefert Datum und Uhrzeit, ebenfalls in UTC.

Probier es aus

Die Pflichtfelder

Die Tabelle deliveries hat id, supplier_id, amount und status. Mach den Lieferanten und den Betrag zu Pflichtfeldern, und den Status zum Pflichtfeld mit dem Standardwert 'expected'.

SQLleere Datenbank

Die Idee

UNIQUE

UNIQUE verbietet zwei gleiche Werte in der Spalte. Eine Firma hat eine Umsatzsteuernummer:

SQLleere Datenbank

Manchmal ist es das Paar, das eindeutig ist. Jeder Lieferant nennt einen Preis für ein Produkt. Zwei Lieferanten dürfen dasselbe Produkt anbieten, und ein Lieferant bietet viele Produkte an. Die Regel wird getrennt nach den Spalten geschrieben, mit beiden Spalten in Klammern:

SQLleere Datenbank

Die ersten drei Zeilen gehen hinein. Die vierte ist ein zweiter Preis von Lieferant 1 für Produkt 1.

Genauer, für Neugierige

UNIQUE erlaubt viele NULL: Zwei Lieferanten ohne Umsatzsteuernummer zählen nicht als gleich, weil NULL nicht gleich NULL ist. Wenn die Umsatzsteuernummer Pflicht ist, schreib vat TEXT NOT NULL UNIQUE. PostgreSQL arbeitet genauso. SQL Server lässt in eine UNIQUE-Spalte standardmäßig nur ein NULL.

Die Idee

CHECK

CHECK (Bedingung) lässt die Zeile nur hinein, wenn die Bedingung wahr ist. Die Bedingung ist wie die in WHERE:

SQLleere Datenbank

Wenn die Bedingung mehrere Spalten betrifft, steht CHECK nach den Spalten. Eine Aktion darf nicht enden, bevor sie beginnt:

SQLleere Datenbank

Die Meldung von SQLite sagt, welche Bedingung verletzt wurde. Halte die Bedingungen also kurz und klar.

Sieh es dir an

CHECK lässt NULL durch

Die Bewertung geht von 1 bis 5. Und wenn sie nicht angegeben ist?

SQLleere Datenbank

Sie ist hineingekommen. CHECK weist die Zeile nur ab, wenn die Bedingung falsch ist. NULL BETWEEN 1 AND 5 ist „unbekannt“, wie jeder Vergleich mit NULL. Das ist das Gegenteil von WHERE, das nur behält, was wahr ist.

Hier ist das richtig: Ein neuer Lieferant hat noch keine Bewertung. Aber wenn der Wert Pflicht ist, reicht CHECK nicht. Du brauchst zusätzlich NOT NULL.

Probier es aus

Die Preise der Lieferanten

Die Tabelle supplier_prices hat supplier_id, product_id und price. Der Preis ist Pflicht und größer als 0, und jeder Lieferant hat für ein bestimmtes Produkt nur einen Preis. Ergänze die Regeln.

SQLleere Datenbank

Die Idee

PRIMARY KEY

Den Primärschlüssel kennst du schon: die Spalte, an der man eine Zeile erkennt. In CREATE TABLE ist er ein Constraint wie die anderen. Er lässt keine zwei Zeilen mit demselben Schlüssel hinein:

SQLleere Datenbank

Hat der Schlüssel zwei Spalten, wird er getrennt geschrieben, wie UNIQUE. So ist es in order_items: Ein Produkt steht einmal in einer Bestellung, und die Menge steht in quantity.

order_items

  • PKorder_idinteger→ orders
  • PKproduct_idinteger→ products
  • quantityinteger *
  • unit_pricereal *
Genauer, für Neugierige

SQLite hat eine alte Eigenheit: Ein Primärschlüssel, der nicht INTEGER PRIMARY KEY ist, akzeptiert NULL. Führ es aus:

SQLleere Datenbank

Zwei Gutscheine ohne Code. Das ist ein Fehler aus den frühen Versionen, der geblieben ist, damit alte Programme nicht kaputtgehen. In einer STRICT-Tabelle nimmt der Primärschlüssel kein NULL. Überall sonst schreib code TEXT NOT NULL PRIMARY KEY. In PostgreSQL und MySQL ist der Primärschlüssel immer NOT NULL.

Übung

Die Lieferanten, richtig gemacht

Lege die endgültige Tabelle suppliers an: id (Primärschlüssel), name (Pflicht), vat (Umsatzsteuernummer, Pflicht und ohne Wiederholungen), city (Pflicht, mit dem Standardwert 'Sofia') und rating (eine ganze Zahl von 1 bis 5, darf fehlen). Die Prüfung versucht auch, schlechte Lieferanten hinzuzufügen.

SQLleere Datenbank

Test

Teste dich

1. Die Spalte ist city TEXT NOT NULL DEFAULT 'Sofia'. Was passiert bei einem INSERT, der keine Stadt angibt?
2. Wie sagst du „ein Lieferant hat einen Preis pro Produkt“, wenn zwei Lieferanten dasselbe Produkt anbieten dürfen?
3. Die Spalte ist rating INTEGER CHECK (rating BETWEEN 1 AND 5). Was kommt hinein?
4. Was bedeutet PRIMARY KEY (order_id, product_id) in order_items?

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