SemaTrain Logo Ein Fachportal von SemaTrain

Daten ändern: INSERT, UPDATE, DELETE (DML)

Sie lernen DML so, wie man es in der Praxis macht: sicher, nachvollziehbar und mit Transaktionen. Fokus: INSERT, UPDATE, DELETE – plus „Safety-Workflow“.

Safety-Regel: Bei UPDATE/DELETE immer erst SELECT mit derselben WHERE-Bedingung testen.

SQL Grundlagen Schulung – Kursbezug

Dieses Kapitel ist Teil des Lernpfads zur SQL Grundlagen Schulung. Termine & Buchung laufen über SemaTrain.de.

Fokus: DML (INSERT, UPDATE, DELETE) + sicherer Workflow mit SELECT und Transaktionen.

Worum geht’s?

Safety UPDATE/DELETE: Erst SELECT ... WHERE ... prüfen → dann UPDATE/DELETE mit identischer WHERE.

Schema (Kontext)

Wir bleiben konsistent zum Lernpfad-Schema aus Kapitel 01–04:

Schema-Reminder (SQL)
-- kurse(kurs_id, kurs_name)
-- trainer(trainer_id, name)
-- termine(termin_id, kurs_id, trainer_id, start_datum, ort, format, dauer_tage, preis_eur)
-- buchungen(buchung_id, termin_id, name, email, created_at)

Lehr-/Lernziele

INSERT

INSERT ... VALUES (konsistent zum Schema) (SQL)
-- 1) Kurs anlegen
INSERT INTO kurse (kurs_id, kurs_name)
VALUES (10, 'SQL Grundlagen Schulung');

-- 2) Trainer anlegen
INSERT INTO trainer (trainer_id, name)
VALUES (10, 'Gasttrainer');

-- 3) Termin anlegen (trainer_id optional -> kann auch NULL sein)
INSERT INTO termine (
  termin_id, kurs_id, trainer_id, start_datum, ort, format, dauer_tage, preis_eur
) VALUES (
  1001, 10, 10, '2026-02-23', 'Hamburg', 'Praesenz', 3, 1428.00
);

-- 4) Buchung anlegen (FK: buchungen.termin_id -> termine.termin_id)
INSERT INTO buchungen (buchung_id, termin_id, name, email)
VALUES (5001, 1001, 'Max Mustermann', 'max@example.com');
INSERT mehrerer Zeilen (Batch)
Mehrere Zeilen in einem INSERT (SQL)
-- Mehrere Termine in einem Rutsch (SQLite/MySQL/PostgreSQL gängig)
INSERT INTO termine (
  termin_id, kurs_id, trainer_id, start_datum, ort, format, dauer_tage, preis_eur
) VALUES
  (1002, 10, NULL, '2026-03-09', 'Hamburg', 'Online',   3, 1428.00),
  (1003, 10, 10,   '2026-04-14', 'Berlin',  'Praesenz', 3, 1490.00);
INSERT…SELECT (Daten aus Query übernehmen)
INSERT ... SELECT (SQL)
-- Beispiel: Eine Buchung für alle Termine eines Kurses erzeugen (didaktisch!)
-- In echt: eher NICHT so, aber zeigt INSERT...SELECT.
INSERT INTO buchungen (buchung_id, termin_id, name, email)
SELECT
  900000 + t.termin_id AS buchung_id,
  t.termin_id,
  'Testkunde'          AS name,
  'test@example.com'   AS email
FROM termine AS t
WHERE t.kurs_id = 10;

Praxis-Tipp: In Apps nutzt man Parameter/Prepared Statements und generiert IDs typischerweise automatisch.

UPDATE

Workflow: 1) SELECT2) BEGIN3) UPDATE4) Prüfen5) COMMIT/ROLLBACK

Safety Schritt 1: SELECT Preview (SQL)
-- Preview: Welche Termine wären betroffen?
SELECT termin_id, kurs_id, start_datum, ort, format, preis_eur
FROM termine
WHERE kurs_id = 10
  AND format = 'Online';
UPDATE ... SET ... WHERE (SQL)
-- Preis für Online-Termine des Kurses anpassen (mit WHERE!)
UPDATE termine
SET preis_eur = preis_eur + 50.00
WHERE kurs_id = 10
  AND format = 'Online';
Typischer Unfall: UPDATE ohne WHERE
UPDATE ohne WHERE vermeiden (SQL)
-- NICHT so! Ohne WHERE werden ALLE Zeilen geändert.
-- UPDATE termine SET preis_eur = 1490.00;

-- Besser: Primärschlüssel nutzen (maximal eindeutig)
UPDATE termine
SET preis_eur = 1490.00
WHERE termin_id = 1002;

DELETE

Safety Schritt 1: SELECT Preview (SQL)
-- Preview: Welche Buchungen würden gelöscht?
SELECT buchung_id, termin_id, name, email, created_at
FROM buchungen
WHERE email = 'test@example.com';
DELETE ... WHERE (SQL)
-- Löschen (mit WHERE!)
DELETE FROM buchungen
WHERE email = 'test@example.com';
FK-Falle: Termin löschen trotz Buchungen?
Delete-Reihenfolge bei Foreign Keys (SQL)
-- Wenn buchungen(termin_id) per FOREIGN KEY auf termine(termin_id) zeigt,
-- kann das Löschen eines Termins scheitern, solange Buchungen existieren.

-- 1) Erst Child-Records löschen ...
DELETE FROM buchungen
WHERE termin_id = 1001;

-- ... dann Parent löschen:
DELETE FROM termine
WHERE termin_id = 1001;

-- Alternative (Schema-Entscheidung): ON DELETE CASCADE beim FK,
-- dann würden Buchungen automatisch mitgelöscht. (High impact!)

Praxis: „CASCADE“ ist mächtig – sollte bewusst entschieden und dokumentiert werden.

Transaktionen (BEGIN / COMMIT / ROLLBACK)

Transaktionen sind Ihr Sicherheitsnetz. In vielen Tools ist Autocommit aktiv – im Zweifel bewusst starten.

BEGIN … UPDATE … COMMIT/ROLLBACK (SQL)
-- Typischer Safety-Flow (DB-abhängig: BEGIN / START TRANSACTION)
BEGIN;

-- Preview
SELECT termin_id, preis_eur
FROM termine
WHERE termin_id = 1002;

-- Änderung
UPDATE termine
SET preis_eur = preis_eur + 50.00
WHERE termin_id = 1002;

-- Prüfen
SELECT termin_id, preis_eur
FROM termine
WHERE termin_id = 1002;

-- Entscheiden:
-- COMMIT;   -- übernehmen
-- ROLLBACK; -- zurückrollen

Typische Stolperfallen

Praxisaufgabe

  1. Füge einen Kurs und einen Termin ein (INSERT).
  2. Füge eine Buchung für den Termin ein (INSERT).
  3. Ändere den Preis des Termins (UPDATE) – mit Preview-SELECT.
  4. Lösche testweise die Buchung (DELETE) – mit Preview-SELECT.
  5. Führe UPDATE/DELETE innerhalb einer Transaktion aus und entscheide dich für COMMIT/ROLLBACK.
Lösungsvorschlag anzeigen
Lösung: INSERT/UPDATE/DELETE mit Safety + Transaktion (SQL)
-- 1) Kurs + Termin anlegen
INSERT INTO kurse (kurs_id, kurs_name)
VALUES (20, 'SQL Grundlagen Schulung (Praxis)');

INSERT INTO termine (
  termin_id, kurs_id, trainer_id, start_datum, ort, format, dauer_tage, preis_eur
) VALUES (
  2001, 20, NULL, '2026-06-01', 'Hamburg', 'Online', 3, 1428.00
);

-- 2) Buchung anlegen
INSERT INTO buchungen (buchung_id, termin_id, name, email)
VALUES (8001, 2001, 'Erika Musterfrau', 'erika@example.com');

-- 3+4+5) Sicher ändern in Transaktion
BEGIN;

-- Preview Preis
SELECT termin_id, preis_eur
FROM termine
WHERE termin_id = 2001;

-- Update Preis
UPDATE termine
SET preis_eur = preis_eur + 50.00
WHERE termin_id = 2001;

-- Preview Delete (Buchung)
SELECT buchung_id, termin_id, email
FROM buchungen
WHERE buchung_id = 8001;

-- Delete Buchung
DELETE FROM buchungen
WHERE buchung_id = 8001;

-- Entscheiden:
-- COMMIT;
-- ROLLBACK;

Kurz-Takeaways

Quiz: DML (INSERT/UPDATE/DELETE)

1. (LZ2) Was ist der wichtigste Safety-Schritt vor UPDATE?

2. (LZ3) Was passiert bei DELETE ohne WHERE?

3. (LZ1) Wofür steht INSERT ... SELECT?

4. (LZ4) Wozu dient ROLLBACK in einer Transaktion?

Praxisaufgabe

Mini-Projekt: Safe-Change Runbook (INSERT → UPDATE → DELETE, mit Transaktion)

Sie schreiben ein „Runbook“ (eine reproduzierbare Abfolge von Queries), um Änderungen sicher durchzuführen: Preview → BEGIN → Change → Verify → COMMIT/ROLLBACK. Ziel ist nicht „viel SQL“, sondern ein sauberer Praxis-Workflow.

Beitrag zu den Lehr-/Lernzielen: LZ1 (INSERT), LZ2 (UPDATE sicher), LZ3 (DELETE sicher), LZ4 (Transaktionen).

Stufe A – Setup (INSERT)

Stufe B – Safety Preview (SELECT)

Stufe C – Controlled Change (BEGIN → UPDATE/DELETE)

Stufe D – Verify & Decision

Musterlösung (Runbook)
Projektlösung: Safe-Change Runbook (DML + Transaktion) (SQL)
-- ==========================================================
-- Stufe A – Setup (INSERT)
-- IDs sind hier absichtlich explizit (didaktisch).
-- ==========================================================

INSERT INTO kurse (kurs_id, kurs_name)
VALUES (9100, 'SQL Grundlagen Schulung (Runbook-Test)');

INSERT INTO termine (
  termin_id, kurs_id, trainer_id, start_datum, ort, format, dauer_tage, preis_eur
) VALUES (
  9101, 9100, NULL, '2026-06-15', 'Hamburg', 'Online', 3, 1428.00
);

INSERT INTO buchungen (buchung_id, termin_id, name, email)
VALUES (9102, 9101, 'Testkunde', 'test@example.com');

-- ==========================================================
-- Stufe B – Preview (Safety-SELECT)
-- ==========================================================

SELECT kurs_id, kurs_name
FROM kurse
WHERE kurs_id = 9100;

SELECT termin_id, kurs_id, start_datum, ort, format, preis_eur
FROM termine
WHERE termin_id = 9101;

SELECT buchung_id, termin_id, email
FROM buchungen
WHERE buchung_id = 9102;

-- ==========================================================
-- Stufe C – Controlled Change in Transaktion
-- ==========================================================

BEGIN;

-- C1) Preis +50 €
UPDATE termine
SET preis_eur = preis_eur + 50.00
WHERE termin_id = 9101;

-- C2) Child zuerst löschen (FK-sicher)
DELETE FROM buchungen
WHERE buchung_id = 9102;

-- C3) Parent danach löschen
DELETE FROM termine
WHERE termin_id = 9101;

-- ==========================================================
-- Stufe D – Verify
-- ==========================================================

-- Kurs existiert noch:
SELECT kurs_id FROM kurse WHERE kurs_id = 9100;

-- Termin/Buchung sollten weg sein:
SELECT termin_id FROM termine WHERE termin_id = 9101;
SELECT buchung_id FROM buchungen WHERE buchung_id = 9102;

-- Entscheidung:
-- COMMIT;
-- ROLLBACK;

Ausblick: Im nächsten Kapitel (Subqueries/Views/Index) speichern wir finale Reports als Views und beschleunigen Abfragen mit Indizes – der Safety-Workflow bleibt dabei identisch.