Johannes Schildgen

Sprachkurs SQL

Das Datenbanken-Hörbuch

Sprachkurs SQL - Das Datenbanken-Hörbuch

Lerne die Datenbanksprache SQL einfach während der Autofahrt, in der U-Bahn, beim Kochen oder Putzen. In diesem Hörbuch lernst du die Grundlagen relationaler Datenbanken und du erfährst, was ein ER-Diagramm, das relationale Modell und die relationale Algebra ist. Und natürlich lernst du alles zu SQL.

Die Sprache SQL besteht aus drei Teilen. Der erste ist die DDL, die Data-Definition-Language. Du wirst beispielsweise lernen, wie du mit CREATE TABLE ein Datenbankschema anlegst. Die zweite Teilsprache von SQL ist die Data-Manipulation-Language DML. Mit INSERT kannst du Zeilen in deine Tabellen einfügen, mit UPDATE Änderungen an diesen vornehmen, du kannst sie mit DELETE löschen und natürlich erfährst du auch alle Details zum SELECT-Kommando. Zudem wird auch auf die Data-Control-Language DCL sowie auf Transaktionen, Trigger und Stored Procedures eingegangen, damit du am Ende des Hörbuches das Wichtigste zu SQL und relationalen Datenbanken weißt.

Das innovative Format, SQL mittels eines Hörbuchs zu lernen, bietet neuartige Möglichkeiten zur Lernkontrolle in Form von interaktiven Quizzes: Spreche SQL, mache Fehler und lerne dabei.

Hörbuch kaufen

Audible

Unterwegs hören mit der App.

Amazon

Als MP3-CD kaufen.

Itunes

Perfekt für iPhone-Nutzer.

Google Play

Direkt aufs Android-Smartphone.

Kapitelübersicht und Begleitmaterial

Ein Klick auf ein Kapitel zeigt dir die dazugehörigen Begleitmaterialien und Beispielanfragen an. Eine vollständige Übersicht über alle 115 Audio-Tracks kann hier als PDF-Datei heruntergeladen werden.

In der Einleitung erzähle ich von einem Veranstaltungskalender, den ich ohne den Einsatz einer Datenbank programmiert habe. Er ist in PHP entwickelt und speichert die einzelnen Events in einer CSV-Datei, die die folgende Struktur hat:

24.01.2004,Theaterabend
07.02.2004,Familienabend

Nach einigen Erweiterungen und Anpassungen sah die Datei dann am Ende so aus:

24.01.2004|Theaterabend||Theatergruppe
07.02.2004|Familienabend|http://www.example.com|Feuerwehr
21.02.2004|Sportfest, Zaubershow||Sportverein

Im Kapitel über Datenbanken erfährst du den Unterschied zwischen einer Datenbank, einem Datenbanksystem und einem Datenbankmanagementsystem. Dazu gibt es auch einen tollen Wikipedia-Artikel.

Das ER-Diagramm, welches im Hörbuch vorgestellt wird, könnte in etwa so aussehen:

Ich habe das Diagramm mit dem Online-ER-Diagramm-Generator ERDPlus erstellt. Leider verwendet ERDPlus nicht die 1/n/m-Syntax für Beziehungstypen. Daher habe ich diese Annotationen einfach nachträglich hinzugefügt.

Wenn wir unser ER-Diagramm in Relationen überführen, ergibt sich das folgende Schema (mit Beispieldaten):

KUNDEN
KundennummerNameEMailgeworben_von
5Peterpeter@example.comNULL
8Annaanna@example.com5
PRODUKTE
ProduktnummerBezeichnungPreisHersteller
17Schokoriegel0.89Monsterfood
29Spülmaschinentabs3.99Calgonte
88Katzenfutter4.99NULL
HERSTELLER
FirmaLand
CalgonteItalien
MonsterfoodUSA
HolzkopfÖsterreich
BEWERTUNGEN
KundennummerProduktnummerSterneProduktnummer
5174Guter Schokoriegel, aber die Verpackung geht schwer auf
5291Mein Geschirr wird nicht sauber!

Auf https://dbis-uibk.github.io/relax/ ist ein Relational-Algebra-Calculator (RelaX) zu finden. Das Webshop-Schema aus dem Hörbuch lässt sich mittels folgender Gist-ID importieren: d67f16874b528abc6e6c88d07a50b2dc

SQL

Interessante Zusatzinfos über die Sprache SQL findest du bei Wikipedia. Außerdem möchte ich hier auf die Webseiten der im Hörbuch vorgestellten Datenbankmanagementsysteme MySQL, MariaDB, PostgreSQL, SQLite, Oracle, DB2 und Microsoft SQL Server verlinken.

In den nun folgenden Code-Beispielen findest du Links zur SQL-Fiddle. Dort kannst du die SQL-Anfragen live ausprobieren und nach deinen Wünschen anpassen.

-- http://sqlfiddle.com/#!17/11955/1
CREATE TABLE kunden (kundennummer INT PRIMARY KEY, name VARCHAR(100), email VARCHAR(500) UNIQUE, passwort CHAR(32));
CREATE TABLE hersteller (firma VARCHAR(50) PRIMARY KEY, land VARCHAR(100));
CREATE TABLE produkte (produktnummer INT PRIMARY KEY, bezeichnung VARCHAR(100) NOT NULL, preis DECIMAL(9,2),
                       hersteller VARCHAR(50) REFERENCES hersteller(firma) ON DELETE SET NULL ON UPDATE CASCADE);
CREATE TABLE bewertungen (kundennummer INT REFERENCES kunden(kundennummer),
                          produktnummer INT REFERENCES produkte(produktnummer),
                          sterne INT DEFAULT 5 CHECK(sterne BETWEEN 1 AND 5),
                          bewertungstext VARCHAR(100000),
                          PRIMARY KEY(kundennummer, produktnummer));

CREATE TABLE bewertungslikes (liker INT REFERENCES kunden(kundennummer),
                              kundennummer INT,
                              produktnummer INT,
                              PRIMARY KEY(liker, kundennummer, produktnummer),
                              FOREIGN KEY(kundennummer, produktnummer) REFERENCES bewertungen(kundennummer, produktnummer));

Hier sind einfach mal ein Paar Beispielkommandos aus dem DML-Kapitel. Wenn du sie in der SQL-Fiddle ausprobieren willst, musst du sie in das linke Eingabefenster eingeben.

-- http://sqlfiddle.com/#!17/11955/1
INSERT INTO kunden (kundennummer, name, email) VALUES (  9, 'Jürgen', 'juergen@example.com' );
UPDATE produkte SET preis = preis + 1;
UPDATE produkte SET preis = 4.49 WHERE produktnummer = 29;
UPDATE produkte SET preis = preis * 2 WHERE hersteller = 'Calgonte';
DELETE FROM produkte WHERE produktnummer = 29;
DELETE FROM produkte WHERE hersteller = 'Calgonte' OR hersteller = 'Monsterfood';
DELETE FROM produkte;
TRUNCATE TABLE produkte;
-- http://sqlfiddle.com/#!17/ab249/2
select * FROM produkte;
SELECT bezeichnung, preis FROM produkte;
SELECT * FROM produkte WHERE preis > 1;
SELECT * FROM produkte WHERE produktnummer = 17;
SELECT * FROM produkte WHERE hersteller IS NULL;
SELECT * FROM produkte WHERE preis > 1 AND hersteller = 'Monsterfood';
SELECT * FROM produkte WHERE preis BETWEEN 1 AND 2;
SELECT * FROM produkte WHERE hersteller LIKE 'M%';
SELECT * FROM produkte WHERE hersteller LIKE '%e';
SELECT * FROM produkte WHERE bezeichnung LIKE '%maschine%';
SELECT * FROM produkte WHERE upper(bezeichnung) LIKE '%MASCHINE%';
-- http://sqlfiddle.com/#!17/ab249/3
SELECT * FROM produkte, hersteller WHERE produkte.hersteller = hersteller.firma;
SELECT * FROM produkte JOIN hersteller ON produkte.hersteller = hersteller.firma;
SELECT produkte.bezeichnung, hersteller.land FROM produkte JOIN hersteller ON produkte.hersteller = hersteller.firma;
SELECT p.bezeichnung, h.land FROM produkte p JOIN hersteller h ON p.hersteller = h.firma;
SELECT p.produktnummer, p.bezeichnung, p.preis, p.hersteller FROM produkte p JOIN HERSTELLER h ON p.hersteller = h.firma WHERE h.land = 'Italien';
SELECT p.* FROM produkte p, produkte s WHERE p.preis > s.preis AND s.bezeichnung = 'Spülmaschinentabs';
SELECT * FROM produkte p LEFT JOIN hersteller h ON p.hersteller = h.firma;
SELECT * FROM produkte p RIGHT JOIN hersteller h ON p.hersteller = h.firma;
SELECT * FROM produkte p FULL JOIN hersteller h ON p.hersteller = h.firma;
-- http://sqlfiddle.com/#!17/ab249/4
SELECT count(*) FROM produkte;
SELECT sum(preis) FROM produkte;
SELECT hersteller, avg(preis) FROM produkte GROUP BY hersteller;
SELECT hersteller, avg(preis), sum(preis), max(preis), min(preis) FROM produkte GROUP BY hersteller;
SELECT hersteller, COUNT(*) FROM produkte GROUP BY hersteller;
SELECT COUNT(hersteller) FROM produkte;
SELECT COUNT(DISTINCT hersteller) FROM produkte;
SELECT produktnummer, sterne, COUNT(*) FROM bewertungen GROUP BY produktnummer, sterne;
-- http://sqlfiddle.com/#!17/ab249/5
SELECT *
FROM (SELECT hersteller, count(*) AS anzahl FROM produkte GROUP BY hersteller) p
WHERE anzahl>=2;

SELECT * FROM produkte WHERE preis = (SELECT max(preis) FROM produkte);
SELECT hersteller, count(*) FROM produkte GROUP BY hersteller HAVING count(*) > 5;
SELECT * FROM produkte ORDER BY preis;
SELECT * FROM produkte ORDER BY preis DESC;
SELECT * FROM produkte ORDER BY preis, bezeichnung DESC;
SELECT * FROM produkte ORDER BY hersteller NULLS FIRST;
SELECT * FROM produkte ORDER BY length(bezeichnung);
SELECT * FROM produkte LIMIT 3;
SELECT * FROM produkte ORDER BY preis LIMIT 3;
SELECT * FROM produkte ORDER BY preis LIMIT 3 OFFSET 1;
SELECT hersteller, count(*) FROM produkte WHERE preis >= 2 GROUP BY hersteller HAVING count(*) >= 2 ORDER BY count(*) DESC LIMIT 10;
SELECT land, count(*) FROM hersteller GROUP BY land HAVING count(*) < 5 ORDER BY land;
SELECT h.firma, count(p.produktnummer) FROM hersteller h LEFT JOIN produkte p ON h.firma = p.hersteller GROUP BY h.firma;
-- http://sqlfiddle.com/#!17/ab249/6
SELECT land FROM kunden UNION SELECT land FROM hersteller;
SELECT land FROM kunden UNION ALL SELECT land FROM hersteller;
SELECT land FROM kunden INTERSECT SELECT land FROM hersteller;
SELECT land FROM kunden EXCEPT SELECT land FROM hersteller;
-- http://sqlfiddle.com/#!17/ab249/7
SELECT * FROM kunden WHERE EXISTS ( SELECT * FROM hersteller WHERE hersteller.land = kunden.land );
SELECT * FROM kunden WHERE NOT EXISTS ( SELECT * FROM hersteller WHERE hersteller.land = kunden.land );
SELECT * FROM kunden WHERE land IN (SELECT land FROM hersteller);
SELECT * FROM kunden WHERE land NOT IN (SELECT land FROM hersteller);
-- http://sqlfiddle.com/#!17/ab249/8
SELECT bezeichnung, CAST(preis AS CHAR(9)) FROM produkte;
SELECT bezeichnung, CONCAT(preis, '€') FROM produkte;
SELECT bezeichnung, preis||'€' FROM produkte;
SELECT bezeichnung, CASE WHEN preis=0 THEN 'Gratis' ELSE CAST(preis AS CHAR(9)) END FROM produkte;
SELECT 7+2;
SELECT CONCAT('Hallo', ' ', 'Welt');
-- http://sqlfiddle.com/#!17/ab249/9
SELECT NULL AS hersteller, COUNT(*) FROM produkte
UNION
SELECT hersteller, COUNT(*) FROM produkte GROUP BY hersteller;

SELECT hersteller, COUNT(*) FROM produkte GROUP BY GROUPING SETS ( (), hersteller);
SELECT hersteller, preis, COUNT(*) FROM produkte GROUP BY ROLLUP(hersteller, preis);
SELECT hersteller, preis, COUNT(*) FROM produkte GROUP BY CUBE(hersteller, preis);
-- http://sqlfiddle.com/#!17/ab249/10
SELECT *, RANK() OVER (ORDER BY preis) FROM produkte;
SELECT *, DENSE_RANK() OVER (ORDER BY preis) FROM produkte;
SELECT *, ROW_NUMBER() OVER (ORDER BY preis) FROM produkte;
SELECT *, RANK() OVER (PARTITION BY hersteller ORDER BY preis) FROM produkte;
SELECT *, SUM(preis) OVER () FROM produkte;
SELECT *, SUM(preis) OVER (PARTITION BY hersteller) FROM produkte;
SELECT *, SUM(preis) OVER (PARTITION BY kundennummer) FROM bestellungen;
SELECT *, SUM(preis) OVER (ORDER BY zeit) FROM bestellungen;
SELECT *, SUM(preis) OVER (PARTITION BY kundennummer ORDER BY zeit) FROM bestellungen;
SELECT *, SUM(preis) OVER (ORDER BY zeit ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) FROM bestellungen;
-- http://sqlfiddle.com/#!17/2780f/1
CREATE TABLE PRODUKT_ARCHIV (LIKE PRODUKTE);
INSERT INTO PRODUKT_ARCHIV SELECT * FROM produkte WHERE produktnummer = 88;
INSERT INTO PRODUKTE VALUES(88, 'Katzenfutter', 3.99, NULL) ON CONFLICT (produktnummer) DO UPDATE SET preis = EXCLUDED.preis;
-- http://sqlfiddle.com/#!4/b3713f/1
MERGE INTO produkte p USING neue_produkte n ON (p.produktnummer = n.produktnummer)
WHEN MATCHED THEN UPDATE SET p.preis = n.preis
WHEN NOT MATCHED THEN INSERT (produktnummer, bezeichnung, preis, hersteller) VALUES (n.produktnummer, n.bezeichnung, n.preis, n.hersteller);
-- http://sqlfiddle.com/#!17/ab249/11
WITH teuere_produkte AS (SELECT * FROM produkte WHERE preis > 10)
SELECT * FROM teuere_produkte;

WITH bestellstatistik AS (SELECT kundennummer, COUNT(*) as anzahl FROM bestellungen GROUP BY kundennummer)
SELECT avg(anzahl) FROM bestellstatistik;
-- http://sqlfiddle.com/#!17/ab249/12
WITH RECURSIVE kunden_huelle AS (SELECT kundennummer, geworben_von FROM kunden WHERE geworben_von IS NOT NULL
UNION ALL SELECT r.kundennummer, k.geworben_von FROM kunden_huelle r JOIN kunden k ON r.geworben_von = k.kundennummer WHERE k.geworben_von IS NOT NULL)
SELECT geworben_von, COUNT(*) FROM kunden_huelle GROUP BY geworben_von;
-- http://sqlfiddle.com/#!4/81940/1
SELECT kundennummer, CONNECT_BY_ROOT geworben_von as geworben_von FROM kunden
CONNECT BY PRIOR kundennummer = geworben_von;

WITH kunden_huelle AS
(SELECT kundennummer, CONNECT_BY_ROOT geworben_von as geworben_von FROM kunden
CONNECT BY PRIOR kundennummer = geworben_von)
SELECT geworben_von, count(*) FROM kunden_huelle WHERE geworben_von IS NOT NULL GROUP BY geworben_von;
-- http://sqlfiddle.com/#!17/7ff00/1
CREATE VIEW teuere_produkte AS SELECT * FROM produkte WHERE preis > 10;
CREATE VIEW produkte_view AS SELECT p.produktnummer, bezeichnung, preis, hersteller, avg(sterne) AS bewertung FROM produkte p join bewertungen b ON p.produktnummer = b.produktnummer GROUP BY p.produktnummer, bezeichnung, preis, hersteller;
CREATE USER barbara IDENTIFIED BY pw1234;
GRANT SELECT ON produkte TO barbara;
REVOKE SELECT on produkte FROM barbara;
GRANT SELECT ON teuere_produkte TO barbara;

CREATE VIEW produkte_ohne_preise AS SELECT produktnummer, bezeichnung, hersteller FROM produkte;
CREATE USER kai IDENTIFIED BY pw5678;
GRANT SELECT ON produkte_ohne_preise TO kai;
-- http://sqlfiddle.com/#!17/7e97b/1
CREATE MATERIALIZED VIEW amerikanische_produkte AS SELECT p.* FROM produkte p JOIN hersteller h ON p.hersteller = h.firma AND h.land='USA';
REFRESH MATERIALIZED VIEW amerikanische_produkte;
$connection = new PDO("mysql:dbname=onlineshop;host=localhost", "barbara", "pw1234"));
$connection->exec("INSERT INTO produkte VALUES (88, 'Katzenfutter', 4.99)");
$stmt = $connection->query("SELECT bezeichnung FROM produkte");
while($row = $stmt->fetch()) {
  echo $row['bezeichnung'];
}

$email = "peter@example.com"; $passwort = "pw1234";
$stmt = $connection→prepare("SELECT 1 FROM kunden WHERE email = ? AND passwort = MD5(?)");
$stmt->execute([$email, $passwort]);
if($stmt->fetch()) { echo "Erfolgreich eingeloggt!"; }
-- http://sqlfiddle.com/#!15/6a00a/1
CREATE FUNCTION alles_leeren() RETURNS void AS
$$ BEGIN
 TRUNCATE bewertungen CASCADE;
 TRUNCATE produkte CASCADE;
 TRUNCATE hersteller CASCADE;
 TRUNCATE kunden CASCADE;
END $$ LANGUAGE plpgsql;

select alles_leeren();
-- http://sqlfiddle.com/#!15/a8f17/1
CREATE FUNCTION preiserhoehung(INT, DECIMAL(9,2)) RETURNS void AS
$$ BEGIN
 UPDATE produkte SET preis = preis + $2 WHERE produktnummer = $1;
END $$ LANGUAGE plpgsql;

SELECT preiserhoehung(17, 0.10);

CREATE FUNCTION addieren(int, int) RETURNS INT AS
$$ BEGIN RETURN $1+$2; END $$ LANGUAGE plpgsql;

SELECT addieren(5, 10);

CREATE FUNCTION produkte_von(VARCHAR) RETURNS TABLE
(produktnummer INT, bezeichnung VARCHAR(100), preis DECIMAL(9,2), hersteller VARCHAR(50)) AS
$$ SELECT produktnummer, bezeichnung, preis, hersteller FROM produkte WHERE hersteller = $1 $$ LANGUAGE sql;

SELECT produkte_von('Calgonte');
-- http://sqlfiddle.com/#!17/47fe0/1
CREATE TRIGGER produkte_trigger AFTER INSERT ON produkte
FOR EACH ROW
BEGIN
IF NOT EXISTS ( SELECT * FROM hersteller WHERE firma = NEW.hersteller ) THEN
INSERT INTO hersteller (firma) VALUES (NEW.hersteller);
END IF;
END;
CREATE INDEX produkte_hersteller_idx ON produkte(hersteller);

An dieser Stelle verlinke ich gerne auf den Wikipedia-Artikel zum ACID-Paradigma.

Kontakt? Feedback? Sonstiges?

E-Mail

Händleranfragen erwünscht! Bitte wenden Sie sich an unseren Vertriebspartner
oomoxx media, CD Produktion und DVD Produktion. Mail: vertrieb@oomoxx.de