Aufwärmen · Aufgabe 1 von 7
// B1.4 · ca. 32 Min. · Einstieg
Projekt: die Bibliotheksdatenbank
Nach diesem Projekt haben Sie die Bibliotheksdatenbank, mit der der ganze Kurs arbeitet: books, members und loans, mit passenden Typen angelegt, befüllt und geprüft.
Lektion 4 von 4 in B1 Erste Schritte
Danach können Sie
- Für jede Spalte von books, members und loans einen Typ wählen und die drei Tabellen anlegen
- Die Zeilen mit mehrzeiligen INSERT-Anweisungen laden und NULL schreiben, wo ein Wert unbekannt ist
- Das Ergebnis mit SELECT * … ORDER BY und count(*) prüfen und das Skript wiederholbar machen
Vorhersagen · Aufgabe 2 von 7
Sagen Sie es voraus, bevor Sie weiterlesen: Drei dieser fünf Ausleihen haben kein Rückgabedatum. Was liefert die letzte Anweisung?
CREATE TABLE loans (id integer, loaned_on date, returned_on date); INSERT INTO loans VALUES (1, '2026-09-01', '2026-09-10'), (2, '2026-09-12', NULL), (3, '2026-09-05', '2026-09-20'), (4, '2026-09-15', NULL), (5, '2026-09-18', NULL); SELECT count(*) FROM loans;Üben · Aufgabe 3 von 7
Ordnen Sie jeder Spalte den passenden Typ zu.
Üben · Aufgabe 4 von 7
Linus hat keine E-Mail-Adresse. Ergänzen Sie den Wert, der „unbekannt“ bedeutet.
INSERT INTO members VALUES (3, 'Linus', ____, 'Berlin', '2026-02-10');INSERT INTO members VALUES (3, 'Linus', , 'Berlin', '2026-02-10');Üben · Aufgabe 5 von 7
Bringen Sie die Teile eines wiederholbaren Aufbauskripts in die Reihenfolge, in der sie laufen müssen.
- 1.INSERT INTO books VALUES (1, 'Dune', …), (2, 'Emma', …);
- 2.CREATE TABLE books (id integer, title text, …);
- 3.SELECT count(*) FROM books;
- 4.DROP TABLE IF EXISTS books;
Denksport · Aufgabe 6 von 7
Knobelaufgabe. Die Tabelle loans ist leer. Dieses INSERT hat drei Zeilen, und die zweite enthält einen Tag, den es nicht gibt. Wie viele Zeilen enthält loans danach?
INSERT INTO loans VALUES (1, 1, 1, '2026-09-01', '2026-09-10'), (2, 3, 1, '2026-09-31', NULL), (3, 2, 2, '2026-09-05', '2026-09-20');Anwenden · Aufgabe 7 von 7
Mini-Aufgabe. Gehen Sie vom books-Skript des Beispiels aus. Fügen Sie zwei Bücher, die Sie mögen, mit einem weiteren INSERT mit zwei Zeilen hinzu, ids 7 und 8, und enden Sie mit SELECT count(*) FROM books;. Führen Sie es aus: Die Anzahl muss 8 sein. Lassen Sie dann ein Komma zwischen Ihren zwei Zeilen weg und lesen Sie den Fehler.
Prüfen Sie Ihr Ergebnis anhand dieser Liste
Selbst programmieren
Lesen Sie das ausgearbeitete Beispiel und lösen Sie dann die Übungen. Ihr Code läuft in Ihrem Browser oder auf Ihrem Computer und wird nie hochgeladen.
Ausgearbeitetes Beispiel
Die Tabelle books, gebaut und geprüft
Die erste Tabelle der Bibliothek, so wie das ganze Projekt arbeitet: alte Tabelle löschen, sie mit einem Typ pro Spalte anlegen, alle Zeilen mit einem INSERT laden, dann ansehen und zählen. DROP TABLE IF EXISTS gibt nur einen Hinweis aus, wenn es noch keine Tabelle gibt, wie bei jedem Lauf hier. Auf Ihrem Computer speichern Sie es als main.sql und führen psql -X -q -v ON_ERROR_STOP=1 -f main.sql aus, so oft Sie wollen.
main.sql
-- The library, step 1: books.
DROP TABLE IF EXISTS books;
CREATE TABLE books (
id integer,
title text,
author text,
year integer,
genre text,
copies integer
);
INSERT INTO books VALUES
(1, 'Dune', 'Frank Herbert', 1965, 'sci-fi', 2),
(2, 'Emma', 'Jane Austen', 1815, 'classic', 1),
(3, 'Kindred', 'Octavia E. Butler', 1979, 'sci-fi', 1),
(4, 'Beloved', 'Toni Morrison', 1987, 'fiction', 1),
(5, 'The Hobbit', 'J. R. R. Tolkien', 1937, 'fantasy', 3),
(6, 'Neuromancer', 'William Gibson', 1984, 'sci-fi', 1);
SELECT * FROM books ORDER BY id;
SELECT count(*) AS books FROM books;
Ausführen mit
psql -X -q -v ON_ERROR_STOP=1 -f main.sqlAusgabe
id | title | author | year | genre | copies
----+-------------+-------------------+------+---------+--------
1 | Dune | Frank Herbert | 1965 | sci-fi | 2
2 | Emma | Jane Austen | 1815 | classic | 1
3 | Kindred | Octavia E. Butler | 1979 | sci-fi | 1
4 | Beloved | Toni Morrison | 1987 | fiction | 1
5 | The Hobbit | J. R. R. Tolkien | 1937 | fantasy | 3
6 | Neuromancer | William Gibson | 1984 | sci-fi | 1
(6 rows)
books
-------
6
(1 row)- Ein INSERT fügt alle sechs Zeilen hinzu: ein Komma zwischen den Zeilen, ein Semikolon am Ende.
- id, year und copies sind integer, deshalb richtet psql sie rechtsbündig aus; Text steht linksbündig.
- ORDER BY id zeigt die Zeilen nach id geordnet; ohne es verspricht SQL keine Reihenfolge.
- count(*) zählt die Zeilen: 6, so viele, wie das INSERT hinzugefügt hat.
- Der Hinweis von DROP TABLE IF EXISTS gehört nicht zum Ergebnis; psql gibt ihn getrennt aus, als Meldung.
Ändern und ausführen
Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.
Beim ersten Ausführen lädt Ihr Browser PostgreSQL herunter (bis zu 10.1 MB) und speichert es im Cache. Jeder Lauf beginnt mit einer leeren Datenbank. Ihr Code bleibt auf Ihrem Gerät.
Übungen
Übung 1 von 2
Schritt 2: die Mitglieder
Legen Sie die Tabelle members mit den Spalten id, name, email, city und joined an, jede mit einem passenden Typ, und laden Sie die vier Mitglieder aus der Vorlage mit einem INSERT. Linus hat keine E-Mail und Margaret keine Stadt: Schreiben Sie NULL. Enden Sie mit SELECT * FROM members ORDER BY id;.
Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.
Beim ersten Ausführen lädt Ihr Browser PostgreSQL herunter (bis zu 10.1 MB) und speichert es im Cache. Jeder Lauf beginnt mit einer leeren Datenbank. Ihr Code bleibt auf Ihrem Gerät.
Hinweise
Hinweis 1
id ist integer, joined ist date, die anderen drei Spalten sind text.
Hinweis 2
Ein INSERT INTO members VALUES mit vier Zeilen in Klammern, durch Kommas getrennt. Daten stehen in Anführungszeichen: '2025-01-15'.
Hinweis 3
Die Zeile von Linus: (3, 'Linus', NULL, 'Berlin', '2026-02-10'). NULL steht ohne Anführungszeichen.
Eine Lösung zeigen
Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.
CREATE TABLE members (
id integer,
name text,
email text,
city text,
joined date
);
INSERT INTO members VALUES
(1, 'Ada', 'ada@example.com', 'Berlin', '2025-01-15'),
(2, 'Grace', 'grace@example.com', 'Munich', '2025-03-02'),
(3, 'Linus', NULL, 'Berlin', '2026-02-10'),
(4, 'Margaret', 'margaret@example.com', NULL, '2026-05-20');
SELECT * FROM members ORDER BY id;
Auf dem eigenen Computer ausführen
Installieren Sie PostgreSQL 18 oder neuer. Speichern Sie diese Dateien in einem Ordner, öffnen Sie dort ein Terminal und führen Sie die Befehle unten aus.
main.sql
-- Create the table members (id, name, email, city, joined)
-- and add these four members in one INSERT:
-- 1 Ada ada@example.com Berlin 2025-01-15
-- 2 Grace grace@example.com Munich 2025-03-02
-- 3 Linus (no email) Berlin 2026-02-10
-- 4 Margaret margaret@example.com (no city) 2026-05-20
-- Then list them, ordered by id.
test.sql
-- test: members hat die Spalten id (integer), name, email, city (text) und joined (date)
SELECT count(*) = 5 FROM information_schema.columns
WHERE table_name = 'members'
AND ((column_name = 'id' AND data_type = 'integer')
OR (column_name IN ('name', 'email', 'city') AND data_type = 'text')
OR (column_name = 'joined' AND data_type = 'date'));
-- test: Die Tabelle enthält vier Mitglieder
SELECT count(*) = 4 FROM members;
-- test: Linus hat keine E-Mail (NULL, nicht der Text 'NULL')
SELECT EXISTS (SELECT 1 FROM members WHERE id = 3 AND name = 'Linus' AND email IS NULL AND city = 'Berlin' AND joined = '2026-02-10');
-- test: Margaret hat keine Stadt (NULL)
SELECT EXISTS (SELECT 1 FROM members WHERE id = 4 AND name = 'Margaret' AND email = 'margaret@example.com' AND city IS NULL AND joined = '2026-05-20');
-- test: Das Skript listet die vier Mitglieder auf, nach id sortiert
-- output:
-- id | name | email | city | joined
-- ----+----------+----------------------+--------+------------
-- 1 | Ada | ada@example.com | Berlin | 2025-01-15
-- 2 | Grace | grace@example.com | Munich | 2025-03-02
-- 3 | Linus | | Berlin | 2026-02-10
-- 4 | Margaret | margaret@example.com | | 2026-05-20
-- (4 rows)
psql führt die Dateien auf Ihrem eigenen PostgreSQL-Server aus. Nehmen Sie eine leere Datenbank, die Sie wegwerfen können: Hängen Sie -d und ihren Namen an den Befehl an.
Programm ausführen:
psql -X -q -v ON_ERROR_STOP=1 -f main.sqlFür die Prüfungen gibt es auf Ihrem Computer noch keinen Befehl. Sie stehen in test.sql: Jede Prüfabfrage gibt t aus, wenn sie besteht.
Übung 2 von 2
Schritt 3: die Ausleihen und eine Zählung von allem
setup.sql hat books und members angelegt. Legen Sie die Tabelle loans (id, book_id, member_id, loaned_on, returned_on) an und laden Sie die fünf Ausleihen aus der Vorlage; die offenen haben kein Rückgabedatum. Zählen Sie dann die Zeilen aller drei Tabellen, eine Abfrage pro Tabelle, mit AS benannt als books, members und loans.
Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.
Beim ersten Ausführen lädt Ihr Browser PostgreSQL herunter (bis zu 10.1 MB) und speichert es im Cache. Jeder Lauf beginnt mit einer leeren Datenbank. Ihr Code bleibt auf Ihrem Gerät.
Hinweise
Hinweis 1
Die drei ids sind integer; loaned_on und returned_on sind date.
Hinweis 2
Eine offene Ausleihe hat NULL als Rückgabedatum: (2, 3, 1, '2026-09-12', NULL).
Hinweis 3
SELECT count(*) AS books FROM books; dann dasselbe für members und loans.
Eine Lösung zeigen
Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.
CREATE TABLE loans (
id integer,
book_id integer,
member_id integer,
loaned_on date,
returned_on date
);
INSERT INTO loans VALUES
(1, 1, 1, '2026-09-01', '2026-09-10'),
(2, 3, 1, '2026-09-12', NULL),
(3, 2, 2, '2026-09-05', '2026-09-20'),
(4, 1, 3, '2026-09-15', NULL),
(5, 6, 2, '2026-09-18', NULL);
SELECT count(*) AS books FROM books;
SELECT count(*) AS members FROM members;
SELECT count(*) AS loans FROM loans;
Auf dem eigenen Computer ausführen
Installieren Sie PostgreSQL 18 oder neuer. Speichern Sie diese Dateien in einem Ordner, öffnen Sie dort ein Terminal und führen Sie die Befehle unten aus.
main.sql
-- setup.sql has created books and members.
-- Create loans (id, book_id, member_id, loaned_on, returned_on)
-- and add these five loans in one INSERT:
-- 1 book 1 member 1 2026-09-01 2026-09-10
-- 2 book 3 member 1 2026-09-12 (open)
-- 3 book 2 member 2 2026-09-05 2026-09-20
-- 4 book 1 member 3 2026-09-15 (open)
-- 5 book 6 member 2 2026-09-18 (open)
-- Then count the rows of books, members and loans.
test.sql
-- test: loans hat integer-ids und zwei date-Spalten
SELECT count(*) = 5 FROM information_schema.columns
WHERE table_name = 'loans'
AND ((column_name IN ('id', 'book_id', 'member_id') AND data_type = 'integer')
OR (column_name IN ('loaned_on', 'returned_on') AND data_type = 'date'));
-- test: Die Tabelle enthält fünf Ausleihen
SELECT count(*) = 5 FROM loans;
-- test: Die Ausleihen 2, 4 und 5 sind offen (returned_on ist NULL)
SELECT (SELECT count(*) FROM loans WHERE returned_on IS NULL AND id IN (2, 4, 5)) = 3
AND (SELECT count(*) FROM loans WHERE returned_on IS NULL) = 3;
-- test: Ausleihe 4 ist Buch 1, am 2026-09-15 an Mitglied 3 verliehen
SELECT EXISTS (SELECT 1 FROM loans WHERE id = 4 AND book_id = 1 AND member_id = 3 AND loaned_on = '2026-09-15');
-- test: Das Skript gibt die drei Anzahlen aus: 6, 4 und 5
-- output:
-- books
-- -------
-- 6
-- (1 row)
--
-- members
-- ---------
-- 4
-- (1 row)
--
-- loans
-- -------
-- 5
-- (1 row)
setup.sql
CREATE TABLE books (
id integer,
title text,
author text,
year integer,
genre text,
copies integer
);
INSERT INTO books VALUES
(1, 'Dune', 'Frank Herbert', 1965, 'sci-fi', 2),
(2, 'Emma', 'Jane Austen', 1815, 'classic', 1),
(3, 'Kindred', 'Octavia E. Butler', 1979, 'sci-fi', 1),
(4, 'Beloved', 'Toni Morrison', 1987, 'fiction', 1),
(5, 'The Hobbit', 'J. R. R. Tolkien', 1937, 'fantasy', 3),
(6, 'Neuromancer', 'William Gibson', 1984, 'sci-fi', 1);
CREATE TABLE members (
id integer,
name text,
email text,
city text,
joined date
);
INSERT INTO members VALUES
(1, 'Ada', 'ada@example.com', 'Berlin', '2025-01-15'),
(2, 'Grace', 'grace@example.com', 'Munich', '2025-03-02'),
(3, 'Linus', NULL, 'Berlin', '2026-02-10'),
(4, 'Margaret', 'margaret@example.com', NULL, '2026-05-20');
psql führt die Dateien auf Ihrem eigenen PostgreSQL-Server aus. Nehmen Sie eine leere Datenbank, die Sie wegwerfen können: Hängen Sie -d und ihren Namen an den Befehl an.
Programm ausführen:
psql -X -q -v ON_ERROR_STOP=1 -f setup.sql -f main.sqlFür die Prüfungen gibt es auf Ihrem Computer noch keinen Befehl. Sie stehen in test.sql: Jede Prüfabfrage gibt t aus, wenn sie besteht.
Häufige Fehler
Das Skript ein zweites Mal ausführen
CREATE TABLE books (
id integer,
title text
);
INSERT INTO books VALUES (1, 'Dune'), (2, 'Emma');
Was psql ausgibt
ERROR: relation "books" already existsWarum, und die Lösung
In Ihrer eigenen Datenbank hat der erste Lauf books angelegt, und die Tabelle ist noch da. Ein zweites CREATE TABLE books scheitert, und ON_ERROR_STOP beendet den Lauf. Beginnen Sie das Skript mit DROP TABLE IF EXISTS books;, dann entfernt jeder Lauf zuerst die alte Tabelle und legt sie danach neu an.
'NULL' in Anführungszeichen
CREATE TABLE loans (id integer, loaned_on date, returned_on date);
INSERT INTO loans VALUES
(1, '2026-09-01', '2026-09-10'),
(2, '2026-09-12', 'NULL');
Was psql ausgibt
ERROR: invalid input syntax for type date: "NULL"Warum, und die Lösung
In Anführungszeichen ist 'NULL' Text, die vier Buchstaben N, U, L, L, und eine date-Spalte kann sie nicht als Tag lesen. Schreiben Sie NULL ohne Anführungszeichen, um zu sagen, dass der Wert unbekannt ist. Vorsicht bei text-Spalten: Dort wird 'NULL' angenommen und als Wort gespeichert, das später wie ein Wert aussieht.
Ein fehlendes Komma zwischen Zeilen
CREATE TABLE books (id integer, title text);
INSERT INTO books VALUES
(1, 'Dune')
(2, 'Emma');
Was psql ausgibt
ERROR: syntax error at or near "("Warum, und die Lösung
Die Zeilen eines mehrzeiligen INSERT werden durch Kommas getrennt. Fehlt eines, liest PostgreSQL (1, 'Dune') zu Ende, erwartet keine weitere Klammer und hält beim ( der nächsten Zeile an. Sehen Sie sich das Ende der Zeile vor der an, auf die der Fehler zeigt, und setzen Sie dort das Komma.
PostgreSQL im Browser: PGlite 0.5.8 (PostgreSQL 18.3), Apache-2.0 und PostgreSQL License. Lizenz und Quellcode
Abschlussquiz
5 Fragen, ohne Hinweise. Ab 80 % ist die Lektion abgeschlossen.
Erledigen Sie zuerst alle Aufgaben oben, um das Abschlussquiz freizuschalten.