Inhaltsverzeichnis
Oracle PL/SQL – Kontrollstrukturen
Fach: Informationstechnologie – Datenbanksysteme
Schulstufe: 12. Schulstufe – HTL Informatik
Voraussetzungen: PL/SQL Einführung, anonymer Block, Variablen
Autor: HTL Pinkafeld – IF/IT
1. IF – Einfache Verzweigung
1.1 Syntax
IF bedingung THEN
-- Anweisungen, wenn Bedingung TRUE
END IF;
1.2 Beispiel
DECLARE
v_sal emp.sal%TYPE;
BEGIN
SELECT sal INTO v_sal FROM emp WHERE empno = 7369;
IF v_sal < 1500 THEN
DBMS_OUTPUT.PUT_LINE('Gehalt unter 1500 – Klasse: Einsteiger');
END IF;
END;
/
1.3 IF–ELSE
DECLARE
v_note NUMBER := 3;
BEGIN
IF v_note <= 2 THEN
DBMS_OUTPUT.PUT_LINE('Bestanden mit Auszeichnung');
ELSE
DBMS_OUTPUT.PUT_LINE('Bestanden');
END IF;
END;
/
2. IF–ELSIF–ELSE / END IF – Mehrfachverzweigung
2.1 Syntax
IF bedingung1 THEN
...
ELSIF bedingung2 THEN
...
ELSIF bedingung3 THEN
...
ELSE
...
END IF;
Achtung: Oracle schreibt
ELSIF(kein zweitesE– keinELSEIF!)
2.2 Beispiel: Notenbewertung
DECLARE
v_punkte NUMBER := 78;
v_note NUMBER;
v_text VARCHAR2(20);
BEGIN
IF v_punkte >= 91 THEN v_note := 1; v_text := 'Sehr Gut';
ELSIF v_punkte >= 76 THEN v_note := 2; v_text := 'Gut';
ELSIF v_punkte >= 61 THEN v_note := 3; v_text := 'Befriedigend';
ELSIF v_punkte >= 51 THEN v_note := 4; v_text := 'Genügend';
ELSE v_note := 5; v_text := 'Nicht Genügend';
END IF;
DBMS_OUTPUT.PUT_LINE(v_punkte || ' Punkte → Note ' || v_note || ' (' || v_text || ')');
END;
/
2.3 NULL in Bedingungen
Wenn eine Variable NULL ist, ist jeder Vergleich mit ihr NULL (weder TRUE noch FALSE):
DECLARE
v_x NUMBER := NULL;
BEGIN
IF v_x = 5 THEN -- NULL = 5 → NULL → Zweig wird NICHT ausgeführt
DBMS_OUTPUT.PUT_LINE('Gleich 5');
ELSIF v_x IS NULL THEN -- Korrekte Prüfung auf NULL
DBMS_OUTPUT.PUT_LINE('v_x ist NULL');
END IF;
END;
/
3. CASE – Auswahl
3.1 Einfaches CASE (Simple CASE)
Vergleicht einen Ausdruck mit konkreten Werten:
DECLARE
v_tag NUMBER := TO_NUMBER(TO_CHAR(SYSDATE, 'D')); -- 1=Sonntag, 2=Montag ...
v_name VARCHAR2(20);
BEGIN
CASE v_tag
WHEN 1 THEN v_name := 'Sonntag';
WHEN 2 THEN v_name := 'Montag';
WHEN 3 THEN v_name := 'Dienstag';
WHEN 4 THEN v_name := 'Mittwoch';
WHEN 5 THEN v_name := 'Donnerstag';
WHEN 6 THEN v_name := 'Freitag';
WHEN 7 THEN v_name := 'Samstag';
ELSE v_name := 'Unbekannt';
END CASE;
DBMS_OUTPUT.PUT_LINE('Heute ist ' || v_name);
END;
/
3.2 Durchsuchtes CASE (Searched CASE)
Jede WHEN-Klausel enthält eine eigene Bedingung:
DECLARE
v_gehalt NUMBER := 4500;
v_klasse VARCHAR2(20);
BEGIN
CASE
WHEN v_gehalt < 2000 THEN v_klasse := 'Niedrig';
WHEN v_gehalt < 4000 THEN v_klasse := 'Mittel';
WHEN v_gehalt < 7000 THEN v_klasse := 'Hoch';
ELSE v_klasse := 'Sehr hoch';
END CASE;
DBMS_OUTPUT.PUT_LINE('Gehaltsklasse: ' || v_klasse);
END;
/
3.3 CASE als Ausdruck (in SQL)
SELECT ename,
sal,
CASE
WHEN sal < 1500 THEN 'Einsteiger'
WHEN sal < 3000 THEN 'Fachkraft'
ELSE 'Senior'
END AS gehaltsklasse
FROM emp
ORDER BY sal;
4. Einfache LOOP-Schleife
4.1 Syntax
LOOP
-- Anweisungen
EXIT WHEN bedingung; -- oder: EXIT (unbedingt)
END LOOP;
4.2 Beispiel: Multiplikationstabelle
DECLARE
v_i NUMBER := 1;
v_basis NUMBER := 7;
BEGIN
LOOP
DBMS_OUTPUT.PUT_LINE(v_basis || ' × ' || v_i || ' = ' || (v_basis * v_i));
v_i := v_i + 1;
EXIT WHEN v_i > 10;
END LOOP;
END;
/
4.3 Endlosschleife vermeiden
Ohne EXIT WHEN läuft die Schleife für immer! Immer eine Abbruchbedingung definieren:
-- GEFÄHRLICH – läuft endlos:
LOOP
NULL; -- kein EXIT!
END LOOP;
-- RICHTIG:
LOOP
v_i := v_i + 1;
EXIT WHEN v_i > 100;
END LOOP;
5. WHILE-Schleife
5.1 Syntax
WHILE bedingung LOOP
-- Anweisungen (werden ausgeführt, solange Bedingung TRUE)
END LOOP;
Die Bedingung wird vor jedem Durchlauf geprüft. Wenn sie beim ersten Mal FALSE ist, wird der Block nie ausgeführt.
5.2 Beispiel: Fakultät berechnen
DECLARE
v_n NUMBER := 10;
v_fak NUMBER := 1;
v_zaehler NUMBER := 1;
BEGIN
WHILE v_zaehler <= v_n LOOP
v_fak := v_fak * v_zaehler;
v_zaehler := v_zaehler + 1;
END LOOP;
DBMS_OUTPUT.PUT_LINE(v_n || '! = ' || v_fak);
END;
/
5.3 Vergleich LOOP vs. WHILE
| Merkmal | Einfache LOOP | WHILE |
|---|---|---|
| Prüfzeitpunkt | Am Ende (EXIT WHEN) | Am Anfang |
| Mindestdurchläufe | 1 | 0 |
| Typischer Einsatz | Wenn mindestens ein Durchlauf sicher | Wenn 0 Durchläufe möglich |
6. Numerische FOR-Schleife
6.1 Syntax
FOR zaehlvariable IN [REVERSE] untergrenze..obergrenze LOOP
-- Anweisungen
END LOOP;
Die Zählvariable wird automatisch deklariert und verwaltet. Sie muss nicht im DECLARE-Abschnitt deklariert werden!
6.2 Vorwärts und Rückwärts
BEGIN
-- Vorwärts: 1, 2, 3, 4, 5
FOR i IN 1..5 LOOP
DBMS_OUTPUT.PUT(i || ' ');
END LOOP;
DBMS_OUTPUT.NEW_LINE;
-- Rückwärts: 5, 4, 3, 2, 1
FOR i IN REVERSE 1..5 LOOP
DBMS_OUTPUT.PUT(i || ' ');
END LOOP;
DBMS_OUTPUT.NEW_LINE;
END;
/
6.3 Beispiel: Zinseszins-Tabelle
DECLARE
v_kapital NUMBER := 10000;
v_zinssatz NUMBER := 0.035; -- 3.5 %
BEGIN
DBMS_OUTPUT.PUT_LINE('Jahr | Kapital');
DBMS_OUTPUT.PUT_LINE('-----|--------');
FOR jahr IN 1..10 LOOP
v_kapital := v_kapital * (1 + v_zinssatz);
DBMS_OUTPUT.PUT_LINE(
LPAD(jahr, 4) || ' | ' || TO_CHAR(v_kapital, 'FM999,990.00') || ' €'
);
END LOOP;
END;
/
6.4 FOR mit dynamischen Grenzen
Die Grenzen können Ausdrücke sein, werden aber einmal beim Schleifenstart ausgewertet:
DECLARE
v_von NUMBER := 5;
v_bis NUMBER := 15;
BEGIN
FOR i IN v_von..v_bis LOOP
DBMS_OUTPUT.PUT(i || ' ');
END LOOP;
DBMS_OUTPUT.NEW_LINE;
END;
/
7. Cursor-FOR-Schleife (Vorschau)
Die Cursor-FOR-Schleife (vollständig im Kapitel „Cursor") iteriert automatisch über alle Zeilen einer Abfrage:
BEGIN
FOR r IN (SELECT ename, sal FROM emp WHERE deptno = 20 ORDER BY sal DESC) LOOP
DBMS_OUTPUT.PUT_LINE(r.ename || ': ' || r.sal);
END LOOP;
END;
/
Vorteil: Kein explizites OPEN/FETCH/CLOSE nötig – PL/SQL erledigt das automatisch.
8. EXIT und CONTINUE
8.1 EXIT – Schleife sofort verlassen
DECLARE
v_summe NUMBER := 0;
BEGIN
FOR i IN 1..1000 LOOP
v_summe := v_summe + i;
EXIT WHEN v_summe > 100; -- Bricht ab, sobald Summe > 100
END LOOP;
DBMS_OUTPUT.PUT_LINE('Summe: ' || v_summe);
END;
/
8.2 CONTINUE – Iteration überspringen
CONTINUE springt direkt zum nächsten Schleifendurchlauf (ab Oracle 11g):
BEGIN
FOR i IN 1..10 LOOP
CONTINUE WHEN MOD(i, 2) = 0; -- Gerade Zahlen überspringen
DBMS_OUTPUT.PUT(i || ' '); -- Nur ungerade: 1 3 5 7 9
END LOOP;
DBMS_OUTPUT.NEW_LINE;
END;
/
8.3 Verschachtelte Schleifen mit Labels
Labels erlauben das gezielte Verlassen einer äußeren Schleife:
BEGIN
<<aeussere_schleife>>
FOR i IN 1..5 LOOP
FOR j IN 1..5 LOOP
EXIT aeussere_schleife WHEN i = 3 AND j = 3; -- Beide Schleifen verlassen
DBMS_OUTPUT.PUT('(' || i || ',' || j || ') ');
END LOOP;
DBMS_OUTPUT.NEW_LINE;
END LOOP aeussere_schleife;
DBMS_OUTPUT.PUT_LINE('Fertig.');
END;
/
9. GOTO und Labels
9.1 GOTO (mit Vorsicht verwenden)
GOTO springt zu einem Label im selben Block. Kann den Code schwer lesbar machen – in Ausnahmefällen nützlich:
DECLARE
v_i NUMBER := 1;
BEGIN
<<schleife_start>>
IF v_i <= 5 THEN
DBMS_OUTPUT.PUT_LINE('Iteration: ' || v_i);
v_i := v_i + 1;
GOTO schleife_start;
END IF;
END;
/
Empfehlung:
GOTOnach Möglichkeit vermeiden und stattdessen strukturierte Schleifen verwenden.
9.2 NULL-Anweisung als Platzhalter
NULL ist eine legale Anweisung, die nichts tut. Nützlich als Platzhalter:
BEGIN
IF 1 = 2 THEN
NULL; -- Absichtlich leer – syntaktisch erforderlich
END IF;
END;
/
10. Zusammenfassung und Ausblick
10.1 Übersicht der Kontrollstrukturen
| Struktur | Zweck | Syntax |
|---|---|---|
IF ... END IF |
Einfache Verzweigung | IF b THEN ... END IF |
IF ... ELSIF ... ELSE |
Mehrfachverzweigung | IF b1 THEN ... ELSIF b2 THEN ... |
CASE ... END CASE |
Mehrfachauswahl | CASE x WHEN v THEN ... |
LOOP ... END LOOP |
Bedingte Schleife | mit EXIT WHEN |
WHILE ... LOOP |
Kopfgesteuerte Schleife | prüft vor jedem Durchlauf |
FOR i IN a..b |
Zählschleife | Zähler automatisch verwaltet |
CONTINUE |
Iteration überspringen | ab Oracle 11g |
EXIT |
Schleife verlassen | mit oder ohne Bedingung |
10.2 Häufige Fehler
| Fehler | Problem |
|---|---|
ELSEIF statt ELSIF |
Syntaxfehler – Oracle kennt nur ELSIF |
| Zählvariable im DECLARE deklariert | FOR-Zähler ist implizit – Neudeklaration erzeugt Konflikte |
Fehlendes END IF / END LOOP |
Syntaxfehler |
| NULL in Bedingung vergessen | IF x = NULL ist nie TRUE – IS NULL verwenden! |
10.3 Ausblick
Das nächste Kapitel behandelt Cursor – die Möglichkeit, mehrere Zeilen aus einer SQL-Abfrage zeilenweise zu verarbeiten:
- Implizite Cursor (automatisch für DML)
- Explizite Cursor (manuell mit OPEN / FETCH / CLOSE)
- Cursor-Attribute:
%FOUND,%NOTFOUND,%ROWCOUNT - Cursor-FOR-Schleife