📘 T-SQL Grundkurs – Teil 1 bis 3
Die wichtigsten Konzepte kompakt: SELECT, WHERE, JOINs, Gruppierung, Unterabfragen, DML und Indizes – alles auf einer Seite
📌 Worum geht es in diesem Grundkurs?
ÜBERBLICK
Dieser dreiteilige Grundkurs vermittelt Ihnen die wesentlichen Fähigkeiten, um mit T-SQL (Transact-SQL) auf Microsoft SQL Server zu arbeiten. Sie lernen, Daten abzufragen, zu filtern, zu verknüpfen, zu aggregieren, zu ändern und zu löschen. Zudem erhalten Sie einen Einblick in die Indexoptimierung für bessere Performance. Die Beispiele basieren auf einer einfachen Demo-Datenbank mit den Tabellen
Kunden, Bestellungen und Produkte.
🎯 Ziel: Nach der Lektüre können Sie eigenständig SQL-Abfragen schreiben, Daten analysieren und einfache Wartungsaufgaben durchführen.
📖 Teil 1: Einfache Abfragen – SELECT, FROM, WHERE, ORDER BY
GRUNDLAGEN
SELECT ist das Herzstück jeder Datenabfrage. Mit
FROM legen Sie die Tabelle fest, WHERE filtert Zeilen, ORDER BY sortiert das Ergebnis.
-- Alle Spalten aus der Kundentabelle abrufen
SELECT * FROM dbo.Kunden;
-- Nur bestimmte Spalten, mit Filter und Sortierung
SELECT Nachname, Vorname, Ort
FROM dbo.Kunden
WHERE Ort = 'Berlin'
ORDER BY Nachname ASC;
-- Verwendung von Aliasen (AS)
SELECT Nachname AS Name, Ort AS Stadt
FROM dbo.Kunden;
Wichtige Operatoren in WHERE:
=,>,<,>=,<=,<>(ungleich)LIKEmit Wildcards (%für beliebig viele Zeichen,_für ein Zeichen)INfür eine WertelisteBETWEENfür WertebereicheAND,OR,NOTfür Verknüpfungen
-- Komplexe Filter
SELECT * FROM dbo.Bestellungen
WHERE Bestelldatum BETWEEN '2025-01-01' AND '2025-03-31'
AND Gesamtwert > 100
AND Status IN ('Versendet', 'Bezahlt');
💡 Best Practice: Vermeiden Sie
SELECT * in Produktivumgebungen – listen Sie immer nur die benötigten Spalten auf. Das spart Netzwerkverkehr und beschleunigt die Abfrage.
🔗 Teil 2: JOINs, GROUP BY und Aggregatsfunktionen
FORTGESCHRITTEN
JOINs verbinden mehrere Tabellen über Schlüsselspalten. Die wichtigsten Typen:
INNER JOIN– nur übereinstimmende Zeilen aus beiden TabellenLEFT JOIN– alle Zeilen der linken Tabelle, auch ohne Treffer in der rechtenRIGHT JOIN– analog, aber seltenerFULL OUTER JOIN– alle Zeilen aus beiden Seiten
-- INNER JOIN: Kunden und ihre Bestellungen
SELECT K.Nachname, B.Bestellnummer, B.Bestelldatum
FROM dbo.Kunden K
INNER JOIN dbo.Bestellungen B ON K.KundenID = B.KundenID;
-- LEFT JOIN: Kunden auch ohne Bestellungen (z. B. für Analyse)
SELECT K.Nachname, COUNT(B.Bestellnummer) AS AnzahlBestellungen
FROM dbo.Kunden K
LEFT JOIN dbo.Bestellungen B ON K.KundenID = B.KundenID
GROUP BY K.Nachname
ORDER BY AnzahlBestellungen DESC;
Aggregatsfunktionen wie
COUNT, SUM, AVG, MIN, MAX fassen viele Zeilen zu einem Wert zusammen. In Kombination mit GROUP BY erhalten Sie Zwischensummen pro Kategorie. Die HAVING-Klausel filtert nach der Aggregation (ähnlich wie WHERE, aber für Gruppen).
-- Gesamtumsatz pro Kunde (nur Kunden mit Umsatz über 5000 €)
SELECT
K.KundenID,
K.Nachname,
SUM(B.Gesamtwert) AS Gesamtumsatz
FROM dbo.Kunden K
INNER JOIN dbo.Bestellungen B ON K.KundenID = B.KundenID
GROUP BY K.KundenID, K.Nachname
HAVING SUM(B.Gesamtwert) > 5000
ORDER BY Gesamtumsatz DESC;
📌 Achtung: Spalten in der
SELECT-Liste, die nicht aggregiert werden, müssen in der GROUP BY-Klausel erscheinen. Sonst erhalten Sie einen Fehler (außer in einigen speziellen Datenbankmodi).
📦 Unterabfragen und abgeleitete Tabellen
ADVANCED
Unterabfragen (Subqueries) sind SELECT-Anweisungen in Klammern, die innerhalb einer äußeren Abfrage verwendet werden. Sie können in
WHERE, SELECT, FROM oder HAVING auftreten. Man unterscheidet zwischen:
- Skalare Unterabfragen – liefern genau einen Wert (eine Zeile, eine Spalte).
- Mehrwertige Unterabfragen – liefern eine Spalte mit mehreren Werten (z. B. mit
IN). - Korrelierte Unterabfragen – beziehen sich auf die äußere Abfrage (werden für jede Zeile neu ausgeführt).
-- Skalare Unterabfrage: Kunden mit Bestellungen über dem Durchschnitt
SELECT Nachname, Vorname
FROM dbo.Kunden
WHERE KundenID IN (
SELECT KundenID
FROM dbo.Bestellungen
GROUP BY KundenID
HAVING AVG(Gesamtwert) > (
SELECT AVG(Gesamtwert) FROM dbo.Bestellungen
)
);
-- Abgeleitete Tabelle (Subquery in FROM)
SELECT sub.Jahr, COUNT(*) AS Anzahl
FROM (
SELECT YEAR(Bestelldatum) AS Jahr
FROM dbo.Bestellungen
) sub
GROUP BY sub.Jahr;
💡 Tipp: Korrelierte Unterabfragen können langsam sein. Oft lassen sie sich durch einen JOIN oder einen Fensterausdruck (
ROW_NUMBER() etc.) ersetzen.
✏️ Teil 3: Daten ändern – INSERT, UPDATE, DELETE
DML
DML steht für Data Manipulation Language. Mit diesen Befehlen verändern Sie die Daten in Ihren Tabellen.
-- INSERT: Neue Zeilen hinzufügen
INSERT INTO dbo.Kunden (Nachname, Vorname, Ort)
VALUES (N'Müller', N'Anna', N'Hamburg');
-- INSERT mit SELECT (z. B. Daten kopieren)
INSERT INTO dbo.Kunden_Archiv
SELECT * FROM dbo.Kunden WHERE LetzteBestellung < '2023-01-01';
-- UPDATE: Daten ändern (mit WHERE, sonst alle Zeilen!)
UPDATE dbo.Bestellungen
SET Status = 'Storniert'
WHERE Bestelldatum < '2024-01-01' AND Status = 'Offen';
-- DELETE: Zeilen löschen (auch hier Vorsicht mit WHERE)
DELETE FROM dbo.TempBestellungen
WHERE Bestelldatum < DATEADD(YEAR, -2, GETDATE());
🚨 Warnung: Ein
UPDATE oder DELETE ohne WHERE betrifft alle Zeilen der Tabelle. Stellen Sie sicher, dass Sie vor der Ausführung eine Sicherung haben oder in einer Transaktion arbeiten (BEGIN TRAN / ROLLBACK).
📈 Indizes – Das Fundament für schnelle Abfragen
PERFORMANCE
Indizes sind Hilfsstrukturen, die SQL Server nutzt, um Daten schnell zu finden. Ein Clustered Index (nur einer pro Tabelle) bestimmt die physische Sortierung der Daten. Non‑Clustered Indizes sind separate B‑Bäume, die auf die Datenzeilen verweisen.
-- Clustered Index auf Primärschlüssel (oft automatisch)
CREATE CLUSTERED INDEX idx_Kunden_KundenID ON dbo.Kunden (KundenID);
-- Non‑Clustered Index für häufige Suchkriterien
CREATE NONCLUSTERED INDEX idx_Kunden_Ort ON dbo.Kunden (Ort) INCLUDE (Nachname, Vorname);
-- Eindeutigen Index erzwingen (verhindert Duplikate)
CREATE UNIQUE INDEX idx_Unique_Email ON dbo.Kunden (Email);
Wann brauche ich welchen Index?
- Clustered Index auf Spalten mit vielen Bereichszugriffen (z. B.
BETWEEN,ORDER BY). - Non‑Clustered Index für Spalten in
WHERE-,JOIN- oderORDER BY-Klauseln. INCLUDEfügt zusätzliche Spalten auf Blattebene hinzu, um Key‑Lookups zu vermeiden (Covering Index).- Zu viele Indizes verlangsamen
INSERT,UPDATE,DELETE. Finden Sie die Balance.
💡 Best Practice: Überprüfen Sie regelmäßig fehlende Indizes mit DMVs oder dem Ausführungsplan. Verwenden Sie den Database Tuning Advisor für Empfehlungen.
🔧 Nützliche T-SQL-Funktionen
REFERENZ
String-Funktionen:
LEN(@string)– Länge eines StringsCHARINDEX('M', @string)– Position eines TeilstringsSUBSTRING(@string, start, length)– Teilstring extrahierenUPPER(@string),LOWER(@string)– Groß-/KleinschreibungREPLACE(@string, 'alt', 'neu')– Zeichen ersetzen
GETDATE()– aktuelles Datum und Uhrzeit (Server-Zeit)DATEADD(day, 7, GETDATE())– Datum addierenDATEDIFF(day, Start, Ende)– Differenz zwischen zwei DatenYEAR(Spalte),MONTH(...),DAY(...)– Teile extrahierenFORMAT(GETDATE(), 'yyyy-MM-dd')– Datum formatieren (verbraucht viele Ressourcen)
CAST(Spalte AS INT)– TypumwandlungCONVERT(INT, Spalte)– mit Formatierungsoptionen
✅ Checkliste: So schreiben Sie guten T-SQL-Code
PRAXIS
- Immer WHERE-Klausel prüfen – besonders vor UPDATE/DELETE
- JOINs explizit schreiben – vermeiden Sie implizite Joins (Komma-Syntax)
- Aliase verwenden – Tabellen mit sinnvollen Kürzeln versehen (z. B. K, B, P)
- Niemals SELECT * in Produktion – Spalten explizit aufführen
- Indizes und Statistiken aktuell halten – regelmäßige Wartung einplanen
- Transaktionen kurz halten – BEGIN TRAN ... COMMIT nicht unnötig ausdehnen
- Ausführungspläne verstehen – bei langsamen Abfragen immer den Plan prüfen
- SQL Injection vermeiden – Parameter verwenden, keine zusammengesetzten Strings
📌 Weiterführende Themen: Nach diesem Grundkurs können Sie sich mit Fensterfunktionen (
ROW_NUMBER(), LAG()), Common Table Expressions (CTEs), dynamischen Abfragen, gespeicherten Prozeduren und Fehlerbehandlung (TRY...CATCH) beschäftigen. Viel Erfolg auf Ihrem Weg zum T-SQL-Profi!