4 Kontrollstrukturen in PL/SQL 4.1 4.2 Bedingte Anweisungen................................................................... 4-2 4.1.1 Die IF-THEN-Anweisung.................................................... 4-2 4.1.2 Die IF-THEN-ELSE-Anweisung.......................................... 4-4 4.1.3 Die IF-THEN-ELSIF-Anweisung........................................ 4-4 4.1.4 Die CASE-Anweisung ......................................................... 4-6 Schleifen in PL/SQL ..................................................................... 4-10 4.2.1 Die Basisschleife ............................................................. 4-12 4.2.2 Die FOR-Schleife .............................................................. 4-14 4.2.3 Die WHILE-Schleife.......................................................... 4-16 4.2.4 Verschachtelte Schleifen ................................................. 4-18 1.2.066 / 4053 4-1 4 Kontrollstrukturen in PL/SQL 4 Kontrollstrukturen in PL/SQL 4.1 Bedingte Anweisungen Mit Hilfe von ‘IF‘-Konstrukten lassen sich Bedingungen festlegen, die erfüllt (’TRUE‘) sein müssen, damit die nachfolgende(n) Anweisung(en) ausgeführt werden. Ist das Ergebnis einer Bedingung FALSE oder NULL (z.B., wenn ein Wert in einem Vergleich unbekannt ist), so werden die nachfolgenden Anweisungen nicht ausgeführt. 4.1.1 Die IF-THEN-Anweisung Die ‘IF-THEN‘-Anweisung ist die einfachste Form der bedingten Anweisung. Sie wird wie alle IF-Konstrukte mit 'END IF' abgeschlossen. Alle Anweisungen, die zwischen IF und END IF stehen, werden ausgeführt, wenn die Bedingung, die dem Schlüsselwort IF folgt, TRUE ist. Syntax: IF bedingung THEN Anweisung; {Anweisung;} END IF; Zur besseren Lesbarkeit sollte ein IF-Konstrukt in obiger Form mit eingerücktem Code geschrieben werden. Hinweis: Achtung bei NULL-Werten! Jeder Vergleich mit NULL (außer mittels IS NULL) ergibt NULL (und damit: Bedingung nicht erfüllt!) Beispiel: SELECT mgr INTO v_mgr FROM emp WHERE empno = v_empno; IF v_mgr != 7698 then ... Für empno=7839 ist mgr NULL, und die Bedingung ist damit nicht erfüllt! Alternative: z. B. IF NVL(v_mgr, 0) != 7839 oder: 4-2 IF v_mgr != 7698 OR v_mgr IS NULL 1.2.066 / 4053 Kontrollstrukturen in PL/SQL 4 IF – THEN – END IF 4 Bedingte Anweisungen durch Verwendung von IF-Konstrukten Bedingung muss TRUE ergeben Syntax: IF bedingung THEN Anweisung; {Anweisung} END IF alle Anweisungen zwischen IF und END IF werden nur ausgeführt, wenn Bedingung hinter IF TRUE ist Vergleich mit NULL ist immer FALSE www.unilog.integrata.de www.unilog-integrata.de 4053 / 1.2.036 Folie 2 IF – THEN – END IF (f) 4 Beispiele: IF SQL%FOUND THEN v_count := SQL%ROWCOUNT; DBMS_OUTPUT.PUT_LINE(v_count || ' Zeilen wurden geändert'); COMMIT; END IF; IF a > b THEN v_num := v_num * a; END IF; IF UPPER(v_name) LIKE 'SMI%' THEN INSERT INTO temp (name, date) VALUES (UPPER(v_name), SYSDATE); END IF; www.unilog.integrata.de www.unilog-integrata.de 1.2.066 / 4053 4053 / 1.2.036 Folie 3 4-3 4 4.1.2 Kontrollstrukturen in PL/SQL Die IF-THEN-ELSE-Anweisung Sie ist eine Erweiterung der reinen IF-Anweisung, bei der angegeben wird, was getan werden soll, wenn die Bedingung nicht erfüllt ist. Ist die Bedingung erfüllt, werden alle dem THEN folgenden Anweisungen ausgeführt, die Anweisungen im ELSE-Zweig werden übersprungen. Ist die Bedingung nicht erfüllt, werden nur die Anweisungen im ELSE-Zweig ausgeführt. Syntax: IF bedingung THEN Anweisung; {Anweisung;} ELSE Anweisung; {Anweisung;} END IF; 4.1.3 Die IF-THEN-ELSIF-Anweisung Auch hier wird in den ELSIF-Zweig abgezweigt, wenn die IFBedingung nicht erfüllt ist. Nach ELSIF wird eine andere Bedingung angegeben, die erfüllt sein muss, damit die nachfolgenden Anweisungen ausgeführt werden. Auch hier kann zuletzt noch ein ELSE-Zweig folgen. Der Unterschied zu zwei aufeinanderfolgenden IF-Konstrukten liegt darin, dass der ELSE-Zweig nur erreicht wird, wenn beide Bedingungen nicht erfüllt sind. Syntax: IF bedingung THEN Anweisung; {Anweisung;} {ELSIF bedingung THEN Anweisung; {Anweisung;} } [ELSE Anweisung; {Anweisung;} ] END IF; Hinweis: Alle IF-Konstrukte können beliebig ineinander verschachtelt werden. 4-4 1.2.066 / 4053 Kontrollstrukturen in PL/SQL IF – THEN – ELSE/ELSIF – END IF 4 4 IF-THEN-ELSE Anweisung Der ELSE-Zweig wird ausgeführt, wenn die Bedingung nicht erfüllt ist IF-THEN-ELSIF-ELSE Anweisung Der ELSIF-Zweig wird ausgeführt, wenn die 1. Bedingung nicht erfüllt ist, aber die hinter ELSIF angegebene Bedingung erfüllt ist Der ELSE- Zweig wird ausgeführt, wenn beide Bedingungen nicht erfüllt sind www.unilog.integrata.de www.unilog-integrata.de 4053 / 1.2.036 Folie 4 IF – THEN – ELSE/ELSIF – END IF (f) 4 Beispiele: IF a > b THEN v_num := v_num * a; ELSE v_num := v_num * b; END IF; SELECT job INTO v_job FROM emp WHERE empno = v_no; IF v_job = 'SALESMAN' THEN UPDATE emp SET comm = comm * 1.1 WHERE empno = v_no; ELSIF v_job = 'MANAGER' THEN UPDATE emp SET sal = sal * 1.2 WHERE empno = v_no; ELSIF v_job = 'PRESIDENT' THEN NULL; ELSE UPDATE emp SET sal = sal * 1.5 WHERE empno = v_no; END IF; www.unilog.integrata.de www.unilog-integrata.de 1.2.066 / 4053 4053 / 1.2.036 Folie 5 4-5 4 4.1.4 Kontrollstrukturen in PL/SQL Die CASE-Anweisung Mit der CASE-Anweisung lassen sich Fallunterscheidungen mit vielen möglichen Werten vereinfachen. Syntax 1 (mit Selektor): CASE variable WHEN wert | ausdruck THEN anweisung(en); {WHEN wert | ausdruck THEN anweisung(en);} [ELSE anweisung(en);] END CASE; Syntax 2 (ohne Selektor): CASE WHEN bedingung1 THEN anweisung(en); WHEN bedingung2 THEN anweisung(en); ... [ELSE anweisung(en);] END CASE; Bei Syntax 1 sind auch Ausdrücke oder Funktionsaufrufe als Selektor erlaubt. Die einzigen nicht zulässigen Datentypen sind BLOB, BFILE, Record, Index-by-Tables, Nested Tables, VArrays und Objekttypen. Es wird immer nur ein Zweig der Fallunterscheidung durchlaufen. Falls keine ELSE-Klausel angegeben wird, wird implizit ergänzt: ELSE RAISE CASE_NOT_FOUND; CASE ist auch zulässig als Teil eines Ausdrucks in der Form (hier nur mit Selektor gezeigt): wert := CASE variable WHEN wert1|ausdruck1 THEN ergebnis1 WHEN wert2|ausdruck2 THEN ergebnis2 .... [ELSE ergebnis;] END; 4-6 1.2.066 / 4053 Kontrollstrukturen in PL/SQL 4 CASE 4 Syntax 1 (mit Selektor): CASE variable WHEN wert | ausdruck THEN anweisung(en); {WHEN wert | ausdruck THEN anweisung(en);} [ELSE anweisung(en);] END [CASE]; Syntax 2 (ohne Selektor): CASE WHEN bedingung THEN anweisung(en); {WHEN bedingung THEN anweisung(en);} [ELSE anweisung(en);] END [CASE]; www.unilog.integrata.de www.unilog-integrata.de 1.2.066 / 4053 4053 / 1.2.036 Folie 6 4-7 4 Kontrollstrukturen in PL/SQL Wird hier kein ELSE-Zweig angegeben und trifft keiner der WHENZweige zu, so wird NULL zurückgegeben. Beispiel: undefine pempno ACCEPT pempno PROMPT 'Bitte geben Sie eine Personalnr. ein (z.B. 7900): ' prompt 'Anfangsstand' select * from emp where empno = &pempno; prompt 'Prozedurbeginn..' declare V_gehaltserhoehung NUMBER :=1; v_job emp.job%type; begin SELECT job INTO v_job FROM emp WHERE empno = &pempno; V_gehaltserhoehung := CASE v_job WHEN 'PRESIDENT' THEN 1 WHEN 'SALESMAN' THEN 1.07 WHEN 'MANAGER' THEN 1.05 WHEN 'CLERK' THEN 1.1 WHEN 'ANALYST' THEN 1.04 ELSE 0 END; UPDATE emp SET sal = sal* V_gehaltserhoehung where empno = &pempno; END; / prompt 'End-Zustand' select * from emp where empno = &pempno / 4-8 1.2.066 / 4053 Kontrollstrukturen in PL/SQL 4 Beispiel 4 Beispiel: SELECT job INTO v_job FROM emp WHERE empno = &pempno; v_gehaltserhoehung := CASE v_job WHEN 'PRESIDENT' THEN 1 WHEN 'SALESMAN' THEN 1.07 WHEN 'MANAGER' THEN 1.05 WHEN 'CLERK' THEN 1.1 WHEN 'ANALYST' THEN 1.04 ELSE 0 END; www.unilog.integrata.de www.unilog-integrata.de 1.2.066 / 4053 4053 / 1.2.036 Folie 7 4-9 4 4.2 Kontrollstrukturen in PL/SQL Schleifen in PL/SQL Schleifen ermöglichen es, bestimmte Teile eines PL/SQL-Blockes wiederholt durchlaufen zu lassen. Sie werden auch als LOOP-Anweisungen bezeichnet, da sie alle das Schlüsselwort LOOP beinhalten und mit END LOOP enden. Die EXIT-Anweisung sorgt dafür, dass eine Schleife bedingungslos verlassen wird, die EXIT-WHEN-Anweisung sorgt dafür, dass eine Schleife verlassen wird, wenn die Bedingung erfüllt (TRUE) ist. EXIT kann in einer Schleife mehrmals vorkommen. Es werden 3 Arten von Schleifen in PL/SQL unterschieden: – Basisschleife: unbedingte Schleife – For-Schleife: Schleife mit Zähler – While-Schleife: Schleife mit Bedingung 4-10 1.2.066 / 4053 Kontrollstrukturen in PL/SQL 4 Schleifen in PL/SQL 4 Schleifen in PL/SQL: ermöglichen die wiederholte Abarbeitung der in der Schleife enthaltenen Anweisung(en) können mit EXIT [WHEN] verlassen werden Es gibt drei Typen: Basisschleife (LOOP) FOR-Schleife WHILE-Schleife www.unilog.integrata.de www.unilog-integrata.de 1.2.066 / 4053 4053 / 1.2.036 Folie 8 4-11 4 4.2.1 Kontrollstrukturen in PL/SQL Die Basisschleife Diese Schleifenart kennt weder Schleifenbedingung noch Schleifenzähler, die die Anzahl der Schleifendurchläufe begrenzen. Ohne 'EXIT [WHEN]'-Befehl ist diese Schleife eine Endlosschleife. Syntax: LOOP Anweisung; {Anweisung;} [EXIT [WHEN Bedingung];] {Anweisung;} END LOOP; 4-12 1.2.066 / 4053 Kontrollstrukturen in PL/SQL 4 Basisschleife 4 ist ohne EXIT [WHEN] eine Endlosschleife beginnt mit endet mit LOOP END LOOP Syntax der Basisschleife: LOOP Anweisung; {Anweisung;} [EXIT [WHEN Bedingung];] {Anweisung;} END LOOP; www.unilog.integrata.de www.unilog-integrata.de 1.2.066 / 4053 4053 / 1.2.036 Folie 9 4-13 4 4.2.2 Kontrollstrukturen in PL/SQL Die FOR-Schleife Die FOR-Schleife bietet die Möglichkeit, mit Hilfe eines Schleifenzählers die Anzahl der Schleifendurchläufe vorzugeben. Der Schleifenzähler wird implizit (als INTEGER) deklariert, braucht also im DECLARE-Teil nicht angegeben zu werden. Pro Schleifendurchlauf wird der Zähler automatisch um 1 erhöht bzw. erniedrigt, eine andere Schrittweite kann nicht angegeben werden. Innerhalb der Schleife kann der Zähler wie eine Konstante referenziert werden, es kann ihm aber kein neuer Wert zugewiesen werden (z. B., um eine andere Schrittweite zu erzielen), außerhalb der Schleife ist er nicht definiert. Als Unter- und Obergrenze sind numerische Literale, Variablen und Ausdrücke zulässig, solange sie als Zahlen ausgewertet werden können. Ist die Untergrenze höher als die Obergrenze, so wird die FORSchleife überhaupt nicht betreten, sind beide gleich hoch, so wird sie einmal durchlaufen. Syntax: FOR zaehler IN [REVERSE] Untergrenze..Obergrenze LOOP Anweisung; {Anweisung;} END LOOP; Das Schlüsselwort REVERSE sorgt dafür, dass von der Obergrenze nach unten gezählt wird; dennoch wird die Untergrenze vor der Obergrenze angegeben. Beispiel: DECLARE v_count number; v_job varchar2(9); BEGIN SELECT count(*) INTO v_count FROM emp; FOR i IN 1..v_count LOOP IF mod(i, 5) = 0 THEN DBMS_OUTPUT.PUT_LINE ( i || 'Durchläufe absolviert'); END iF; END LOOP; END; 4-14 1.2.066 / 4053 Kontrollstrukturen in PL/SQL 4 FOR Schleife 4 Ober- und Untergrenze geben die Anzahl der Durchläufe an Schrittweite ist immer 1 Schleifenzähler kann innerhalb der Schleife referenziert, aber nicht verändert werden Defaultmäßig wird hochgezählt, durch REVERSE wird heruntergezählt Beispiel: DECLARE v_count number; v_job varchar2(9); BEGIN SELECT count(*) INTO v_count FROM emp; FOR i IN 1..v_count LOOP IF mod(i, 5) = 0 THEN DBMS_OUTPUT.PUT_LINE ( i || 'Durchläufe absolviert'); END iF; END LOOP; END; www.unilog.integrata.de www.unilog-integrata.de 1.2.066 / 4053 4053 / 1.2.036 Folie 10 4-15 4 4.2.3 Kontrollstrukturen in PL/SQL Die WHILE-Schleife Bei der WHILE-Schleife wird eine Schleifenbedingung vor jedem Durchlauf der Schleife geprüft. Ist die Bedingung TRUE, so wird die Schleife durchlaufen und an den Beginn der Schleife zurückgekehrt. Daher steht bei einer WHILE-Schleife die Anzahl der Iterationen nicht von vornherein fest. Die Schleife wird so lange durchlaufen, bis die Anfangsbedingung FALSE oder NULL liefert. Ist die Bedingung von vornherein FALSE (oder NULL), so wird sie die Schleife überhaupt nicht durchlaufen, bleibt die Bedingung TRUE, so hat man eine Endlosschleife (z. B. WHILE 1 = 1). Syntax: WHILE Bedingung LOOP Anweisung; {Anweisung;} END LOOP; Beispiel: DECLARE v_min number(4); v_found BOOLEAN := FALSE; BEGIN SELECT min(empno) INTO v_min FROM emp; WHILE NOT v_found LOOP v_min := v_min +1; DELETE FROM emp WHERE empno = v_min; v_found := SQL%FOUND; END LOOP; ROLLBACK; DBMS_OUTPUT.PUT_LINE ('Die zweitniedrigste ' || 'empno ist ' || v_min); END; 4-16 1.2.066 / 4053 Kontrollstrukturen in PL/SQL 4 WHILE Schleife 4 vor Schleifendurchlauf wird eine Anfangsbedingung überprüft Syntax: WHILE Bedingung LOOP Anweisung; {Anweisung;} END LOOP; Beispiel: DECLARE v_min number(4); v_found BOOLEAN := FALSE; BEGIN SELECT min(empno) INTO v_min´FROM emp; WHILE NOT v_found LOOP v_min := v_min +1; DELETE FROM emp WHERE empno = v_min; v_found := SQL%FOUND; END LOOP; ROLLBACK; DBMS_OUTPUT.PUT_LINE (‘Die zweitniedrigste empno ist '|| v_min); END; www.unilog.integrata.de www.unilog-integrata.de 1.2.066 / 4053 4053 / 1.2.036 Folie 11 4-17 4 4.2.4 Kontrollstrukturen in PL/SQL Verschachtelte Schleifen Schleifen können beliebig ineinander verschachtelt werden. Bei verschachtelten Schleifen wird durch EXIT nur die aktuelle Schleife verlassen und in die nächsthöhere gewechselt. Werden die Schleifen mit unterschiedlichen Labels benannt, so besteht die Möglichkeit, durch EXIT labelname [WHEN Bedingung]; auch die entsprechend höhere Schleife zu verlassen. Beispiel: DECLARE v_zaehler PLS_INTEGER :=0; v_aussen BOOLEAN := FALSE; v_innen BOOLEAN := FALSE; BEGIN <<Erste_Schleife>> LOOP v_zaehler := v_zaehler +1; EXIT WHEN v_zaehler <10; <<Zweite_Schleife>> LOOP .... EXIT Erste_Schleife WHEN v_aussen =TRUE; -- beide Schleifen verlassen EXIT WHEN v_innen =TRUE; --nur innere Schleife verlassen END LOOP Zweite_Schleife; --hierher wird bei v_innen = TRUE gesprungen ... END LOOP Erste_Schleife; --hierher wird bei v_aussen = TRUE gesprungen ... END; Die Erwähnung des Schleifennamens bei END LOOP ist optional, erhöht aber die Lesbarkeit. 4-18 1.2.066 / 4053 Kontrollstrukturen in PL/SQL 4 Verschachtelte Schleifen 4 SET SERVEROUPUT ON; DECLARE x NUMBER; BEGIN ... FOR i in 1..10 LOOP -- Schleife 1 ... FOR j in 1..10 LOOP -- Schleife 2 x := i * j; DBMS_OUTPUT.PUT_LINE(i || ‘ mal ‘ || j || ‘ = ‘ || x); END LOOP; -- Ende Schleife 2 ... END LOOP; -- Ende Schleife 1 ... END; www.unilog.integrata.de www.unilog-integrata.de 1.2.066 / 4053 4053 / 1.2.036 Folie 12 4-19 4 4-20 Kontrollstrukturen in PL/SQL 1.2.066 / 4053