📋Spickzettel
Standard-SQL kompakt – und wo die großen Datenbanken davon abweichen.
Abfragen
Grundgerüst
SELECT spalte, AGG(x) AS alias FROM tabelle t JOIN andere a ON a.id = t.a_id WHERE bedingung GROUP BY spalte HAVING AGG(x) > 0 ORDER BY alias DESC LIMIT 10 OFFSET 20;
Ausgeführt: FROM → JOIN → WHERE → GROUP BY → HAVING → SELECT → DISTINCT → ORDER BY → LIMIT
Filter-Operatoren
WHERE preis BETWEEN 10 AND 20 AND genre IN ('Krimi', 'Roman') AND titel LIKE 'D%' -- % beliebig, _ genau ein Zeichen AND autor_id IS NOT NULL
CASE
CASE WHEN preis < 15 THEN 'günstig' WHEN preis < 25 THEN 'mittel' ELSE 'teuer' END
Mengenoperationen
SELECT stadt FROM kunden UNION -- ohne Duplikate (UNION ALL: mit) SELECT land FROM autoren; -- INTERSECT: Schnittmenge, EXCEPT: Differenz (Oracle: MINUS)
JOINs
JOIN-Arten
FROM a INNER JOIN b ON … -- nur Paare FROM a LEFT JOIN b ON … -- alle aus a FROM a RIGHT JOIN b ON … -- alle aus b FROM a FULL JOIN b ON … -- alle aus beiden FROM a CROSS JOIN b -- jede mit jeder
Semi- und Anti-Join
WHERE EXISTS (SELECT 1 FROM b WHERE b.a_id = a.id) WHERE NOT EXISTS (SELECT 1 FROM b WHERE b.a_id = a.id)
NOT EXISTS statt NOT IN, wenn NULLs möglich sind
Aggregation
Aggregatfunktionen
COUNT(*) COUNT(x) COUNT(DISTINCT x) SUM(x) AVG(x) MIN(x) MAX(x)
Alle außer COUNT(*) ignorieren NULL
Window Function
RANK() OVER (PARTITION BY genre ORDER BY preis DESC) SUM(x) OVER (ORDER BY datum ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) LAG(x) OVER (ORDER BY datum)
Unterabfragen
CTE
WITH t AS (SELECT …), u AS (SELECT … FROM t) SELECT * FROM u;
Rekursive CTE
WITH RECURSIVE r (id, ebene) AS ( SELECT id, 0 FROM knoten WHERE eltern IS NULL UNION ALL SELECT k.id, r.ebene + 1 FROM knoten k JOIN r ON k.eltern = r.id ) SELECT * FROM r;
Ändern
INSERT / UPDATE / DELETE
INSERT INTO t (a, b) VALUES (1, 'x'), (2, 'y'); INSERT INTO t (a, b) SELECT … FROM …; UPDATE t SET b = 'z' WHERE a = 1; DELETE FROM t WHERE a = 2;
UPDATE/DELETE immer erst als SELECT mit derselben WHERE-Klausel testen
Transaktion
BEGIN; -- Standard: START TRANSACTION … SAVEPOINT s1; … ROLLBACK TO s1; COMMIT; -- oder ROLLBACK;
Schema
CREATE TABLE
CREATE TABLE t ( id INTEGER PRIMARY KEY, name VARCHAR(100) NOT NULL UNIQUE, x_id INTEGER REFERENCES x (id) ON DELETE CASCADE, menge INTEGER DEFAULT 1 CHECK (menge > 0) );
ALTER / INDEX / VIEW
ALTER TABLE t ADD COLUMN notiz TEXT; CREATE INDEX idx_t_name ON t (name); CREATE VIEW v AS SELECT id, name FROM t; DROP TABLE IF EXISTS alt;
Dialekte im Vergleich
| Thema | SQL-Standard | PostgreSQL | MySQL/MariaDB | SQL Server | Oracle | SQLite |
|---|---|---|---|---|---|---|
| Erste n Zeilen | FETCH FIRST n ROWS ONLY | LIMIT n / FETCH FIRST | LIMIT n | TOP (n) / OFFSET … FETCH | FETCH FIRST (ab 12c) | LIMIT n |
| Text verketten | a || b | a || b | CONCAT(a, b) | a + b / CONCAT | a || b | a || b |
| Auto-ID | GENERATED … AS IDENTITY | IDENTITY / SERIAL | AUTO_INCREMENT | IDENTITY(1,1) | IDENTITY (ab 12c) | INTEGER PRIMARY KEY |
| Upsert | MERGE | ON CONFLICT / MERGE (15+) | ON DUPLICATE KEY UPDATE | MERGE | MERGE | ON CONFLICT |
| FULL OUTER JOIN | ja | ja | nein (UNION) | ja | ja | ja (ab 3.39) |
| Bezeichner quoten | "name" | "name" | `name` | [name] | "name" | "name" |
| Boolescher Typ | BOOLEAN | BOOLEAN | TINYINT(1) | BIT | BOOLEAN (ab 23ai) | 0 / 1 |
| Aktuelles Datum | CURRENT_DATE | CURRENT_DATE | CURRENT_DATE | CAST(GETDATE() AS DATE) | CURRENT_DATE / SYSDATE | CURRENT_DATE |
| Leerstring = NULL? | nein | nein | nein | nein | ja ('' ist NULL) | nein |