SQL steht für «Structured Query Language» und ist sozusagen der De-Facto-Standard für Datenbanksprachen bei Relationalen Datenbanken.
SQL-Insel
Select
Die SELECT-Anweisung startet eine Abfrage und liefert als Ergebnis Datensätze zurück. Die SELECT-Syntax sieht wie folgt aus (unvollständig, optionale Angaben in eckiger Klammer, mögliche mehrfache Angaben durch ‚+’ gekennzeichnet):
SELECT [DISTINCT] Auswahlliste
FROM Quelle
[WHERE Where-Klausel]
[GROUP BY (Group-by-Attribut)+
[HAVING Having-Klausel]]
[ORDER BY (Sortierungsattribut [ASC|DESC])+];
2
3
4
5
6
DISTINCT
gibt an, dass aus der Ergebnisrelation gleiche Ergebnistupel entfernt werden sollen. Es wird also jeder Datensatz nur einmal ausgegeben, auch wenn er mehrfach in der Tabelle vorkommt.- «Auswahlliste» bestimmt, welche Spalten der Quelle auszugeben sind (
*
für alle) und ob Aggregatsfunktionen anzuwenden sind. Wie bei allen anderen Aufzählungen werden die einzelnen Elemente mit Komma voneinander getrennt. - «Quelle» gibt an, wo die Daten herkommen. Es können Relationen und Sichten (
VIEW
) angegeben werden und miteinander als kartesisches Produkt oder als Verbund (JOIN
) verknüpft werden. Mit der zusätzlichen Angabe eines Namens können Tupelvariablen besetzt werden, d. h. Relationen für die Abfrage umbenannt werden. - «Where»-Klausel bestimmt Bedingungen, unter denen die Daten ausgegeben werden sollen. In SQL ist hier auch die Angabe von Unterabfragen möglich, so dass SQL streng relational vollständig wird.
- «Group-by-Attribut» legt fest, ob unterschiedliche Werte als einzelne Zeilen ausgegeben werden sollen (
GROUP BY
= Gruppierung) oder aber die Feldwerte der Zeilen durch Addition (SUM
), Durchschnitt (AVG
), Minimum (MIN
), Maximum (MAX
) o.ä. zu einem Ergebniswert zusammengefasst werden, der sich dann auf die Gruppierung bezieht. - «Having-Klausel» ist wie die Where-Klausel, nur dass sich die angegebene Bedingung auf das Ergebnis einer Aggregationsfunktion bezieht (z. B.
HAVING SUM (Betrag) > 0
). - «Sortierungsattribut»: nach
ORDER BY
werden Attribute angegeben, nach denen sortiert werden soll.ASC
gibt dabei aufsteigende (Standard),DESC
absteigende Sortierung an.
Aufgabe: SQL ausführen
Führe die folgenden SQL-Select-Abfragen auf unsere bereits bekannte Film-DB aus und überlege dir wie die Resultate zustande kommen. Übersetze die Anfrage dem Sinn nach in Umgangssprache und notiere dein Ergebnis.
Die SQL-Abfragen kannst du hier ausführen:
👉 SQL-Run
SELECT * FROM movies;
SELECT * FROM actors;
2
SELECT * FROM movies ORDER BY title;
SELECT * FROM movies ORDER BY title DESC;
2
SELECT name FROM actors WHERE sex = "w";
SELECT title FROM movies WHERE year > 2014;
2
SELECT name FROM actors WHERE name = "%el%";
SELECT name FROM actors WHERE name LIKE "%el%";
SELECT title FROM movies WHERE title = "Spotlight";
SELECT title FROM movies WHERE title LIKE "Spotlight";
2
3
4
SELECT SUM(votes) FROM ratings;
SELECT SUM(votes) as total FROM ratings;
2
SELECT sex, COUNT(*) FROM actors
GROUP BY actors.sex;
2
Aufgabe: SQL schreiben
Schreibe SQL-Select-Abfragen für die folgenden Fragen (siehe Aufgabe Kapitel «Relationale Datenbanksysteme»):
- In welchen Filmen hat Michael Keaton mitgespielt?
- Findest du ein Zitat aus dem Film mit der höchsten Bewertung (
ranking
so tief wie möglich)? - Welche Schauspieler haben im Film «Spotlight» mitgespielt?
Joins
Zum Zusammenführen von Daten aus mehreren über Fremdschlüssel verbundene Tabellen verwenden wir bevorzugt den JOIN-Befehl.
id | title | year |
---|---|---|
1 | Argo | 2012 |
2 | 12 Years a Slave | 2013 |
3 | Birdman | 2014 |
4 | Spotlight | 2015 |
5 | Moonlight | 2016 |
6 | The Shape of Water | 2017 |
id | movie_id | quotetext |
---|---|---|
1 | 5 | Little: My name is Chiron, people call me little. |
2 | 5 | Black: It is what it is. |
3 | 3 | Mike Shiner: Popularity is the slutty little cousin of prestige. |
Möchte man nun die beiden Tabellen mit SQL verknüpfen, kann man dies mit einem JOIN
der beiden Tabellen erreichen:
SELECT *
FROM movies JOIN quotes
ON movies.id = quotes.movie_id;
2
3
movies.id | movies.title | movies.year | quotes.id | quotes.movie_id | quotes.quotetext |
---|---|---|---|---|---|
5 | Moonlight | 2016 | 1 | 5 | Little: My name is Chiron, people call me little. |
5 | Moonlight | 2016 | 2 | 5 | Black: It is what it is. |
3 | Birdman | 2014 | 3 | 3 | Mike Shiner: Popularity is the slutty little cousin of prestige. |
JOIN
erstellt eigentlich eine temporäre Tabelle (eine sogenannte Kreuztabelle) aus der wir dann mit SELECT
Datensätze und Attribute auswählen können:
Z.B. Film-Id, -Titel und Zitat aller Filme aus den Jahren 2014 und 2015:
SELECT movies.id, title, quotetext
FROM movies JOIN quotes
ON movies.id = quotes.movie_id
WHERE year = 2014 OR year = 2015;
2
3
4
movies.id | movies.title | quotes.quotetext |
---|---|---|
3 | Birdman | Mike Shiner: Popularity is the slutty little cousin of prestige. |
Wie man sieht fehlt der Film «Spotlight» im Ergebnis. Dies weil es sich beim «normalen» JOIN
um einen sogenannten «Inneren Join» handelt.
Dieser verknüpft die Datensätze der beiden Tabellen. Wenn aber ein Datensatz aus einer Tabelle in der anderen keine Verknüpfung hat, dann wird dieser Datensatz nicht angezeigt. Wenn wir also alle Filme der Jahre 2014 und 2015 haben möchten – inkl. Zitat, falls sie eines haben, sonst halt ohne – dann können wir dies mit einem sogenannten «Linken Join» erreichen:
SELECT movies.id, title, quotetext
FROM movies LEFT JOIN quotes
ON movies.id = quotes.movie_id
WHERE year = 2014 OR year = 2015;
2
3
4
movies.id | movies.title | quotes.quotetext |
---|---|---|
3 | Birdman | Mike Shiner: Popularity is the slutty little cousin of prestige. |
4 | Spotlight |
Neben LEFT JOIN
existiert natürlich auch ein RIGHT JOIN
, welcher alle Datensätze der rechten Tabelle anzeigt, egal ob sie eine Verknüpfung zu einem Datensatz der linken Tabelle haben oder nicht.
Aufgabe: SQL-Joins
Führe die folgenden SQL-Select-Abfragen auf unsere bereits bekannte Film-DB aus und überlege dir wie die Resultate zustande kommen. Übersetze die Anfrage dem Sinn nach in Umgangssprache und notiere dein Ergebnis.
Die SQL-Abfragen kannst du hier ausführen:
👉 SQL-Run
SELECT movies.id, title, rank
FROM movies JOIN ratings
ON movies.id = ratings.movie_id;
2
3
SELECT *
FROM movies
JOIN movies2actors ON movies.id = movies2actors.movie_id
JOIN actors ON actors.id = movies2actors.actor_id;
2
3
4
SELECT title, COUNT(movies2actors.actor_id) as count_actors
FROM movies
JOIN movies2actors ON movies.id = movies2actors.movie_id
GROUP BY movies.id;
2
3
4
SELECT name, COUNT(movies.id) as count_movies
FROM actors
JOIN movies2actors ON actors.id = movies2actors.actor_id
JOIN movies ON movies.id = movies2actors.movie_id
GROUP BY actors.id
HAVING COUNT(movies.id) > 1;
2
3
4
5
6
SELECT actors.name, AVG(rank)
FROM movies
JOIN movies2actors ON movies.id = movies2actors.movie_id
JOIN actors ON actors.id = movies2actors.actor_id
JOIN ratings ON movies.id = ratings.movie_id
GROUP BY actors.id
ORDER BY AVG(rank);
2
3
4
5
6
7
weitere Befehle
Datenmanipulation
Zum Einfügen, Ändern und Löschen von Datensätzen, resp. zum Leeren von ganzen Tabellen.
INSERT INTO Relation [( Attribut+ )] VALUES ( ( Konstante+ ) )+
INSERT INTO Relation [( Attribut+ )] SFW-Block
UPDATE Relation SET (Attribut=Ausdruck)+ [WHERE Where-Klausel]
DELETE FROM Relation [WHERE Where-Klausel]
TRUNCATE Relation
2
3
4
5
- Mit
INSERT
können explizit konstruierte Tupel oder die Ergebnisse eines SFW-Blocks (SELECT-FROM-WHERE
) in eine Relation eingefügt werden. Dabei kann jeweils mehr als eine Zeile verarbeitet werden. - Der Ausdruck aus der
UPDATE
-Anweisung kann insbesondere auch auf das zu manipulierende Attribut Bezug nehmen. - Wird bei
DELETE
dieWHERE
-Klausel weggelassen, werden alle Tupel gelöscht, aber nicht das Relationsschema. - Die
TRUNCATE
-Anweisung leert eine Tabelle vollständig und, was den Hauptunterschied zuDELETE FROM Table
ist, setzt auch jegliche Indizes und Auto-Inkrement-Werte auf die Standardwerte.
Definition des Datenbankschemas
Die SQL-Befehle zur Definition des Datenbankschemas werden wir nur der Vollständigkeit halber kurz anschauen. Heutzutage werden meistens grafische Tools wie z.B. phpMyAdmin (mySQL-DB) oder pgAdmin (PostgreSQL-DB) verwendet, um die Struktur einer Relation anzupassen oder eine neue Relation zu definieren.
CREATE TABLE 'lagerbestand' (
'notebooks_id' varchar(20) NOT NULL,
'bestand' int(11) NOT NULL,
'lieferung' date default NULL,
PRIMARY KEY ('notebooks_id')
)
2
3
4
5
6
Weitere SQL-Befehle dieser Kategorie sind z.B. ALTER
um eine vorhandene Relation abzuändern oder DROP
um eine Relation zu löschen.
Rechteverwaltung
Mit den Befehlen GRANT
und REVOKE
lassen sich Zugriffsrechte auf die Datenbankobjekte einer Datenbank verteilen resp. wieder entfernen.
GRANT SELECT, UPDATE ON TABLE lagerbestand TO group_lager
REVOKE INSERT ON TABLE notebooks FROM PUBLIC
2
Allerdings wird auch diese Aufgabe heute meist über grafische Tools erledigt.