Programmfluss steuern
Im Gegensatz zu SQL, wo Anweisungen in die Reihenfolge ausgeführt werden, in die sie eingegeben wurden, verfügt PL/SQL über Kontrollanweisungen, mit denen Sie den Flow des Programms steuern können.
Informationen zu Kontrollanweisungen
PL/SQL verfügt über drei Kategorien von Kontrollanweisungen: bedingte Auswahlanweisungen, Schleifenanweisungen und sequenzielle Kontrollanweisungen.
Mit Bedingte Auswahlanweisungen können Sie verschiedene Anweisungen für verschiedene Datenwerte ausführen. Die bedingten Auswahlanweisungen sind IF und CASE.
Schleifenanweisungen, mit denen Sie dieselben Anweisungen mit einer Reihe unterschiedlicher Datenwerte wiederholen können. Schleifenanweisungen sind: FOR LOOP, WHILE LOOP und Basis-LOOP. Die EXIT-Anweisung überträgt die Kontrolle an das Ende einer Schleife. Die Anweisung CONTINUE beendet die aktuelle Wiederholung einer Schleife und überträgt die Kontrolle an die nächste Wiederholung. EXIT und CONTINUE haben eine optionale WHEN-Klausel, in der Sie eine Bedingung angeben können.
Mit Sequenzielle Kontrollanweisungen können Sie zu einer angegebenen beschrifteten Anweisung gehen oder keine Aktion ausführen. Die sequenziellen Kontrollanweisungen sind GOTO und NULL.
Siehe auch: Oracle Database PL/SQL Language Reference für einen Überblick über PL/SQL-Kontrollanweisungen
IF-Anweisung verwenden
Mit der Anweisung IF wird eine Reihe von Anweisungen je nach Wert eines Booleschen Ausdrucks entweder ausgeführt oder übersprungen.
Die IF-Anweisung hat folgende Syntax:
IF boolean_expression THEN statement [, statement ]
[ ELSIF boolean_expression THEN statement [, statement ] ]...
[ ELSE statement [, statement ] ]
END IF;
Angenommen, Ihre Firma führt in den ersten zehn Beschäftigungsjahren eines Mitarbeiters zweimal jährlich und nach dem zehnten Jahr nur einmal jährlich eine Evaluierung durch. Sie benötigen eine Funktion, die die Evaluierungsfrequenz eines Mitarbeiters zurückgibt. Sie können den Rückgabewert der Funktion mit einer IF-Anweisung ermitteln, wie in Beispiel 5-4.
Fügen Sie die Funktion EVAL_FREQUENCY dem Body des Packages EMP_EVAL hinzu, jedoch nicht der Spezifikation. Da sich EVAL_FREQUENCY nicht in der Spezifikation befinden, ist es lokal im Package. Es kann nur von anderen Unterprogrammen im Package aufgerufen, nicht aber von außerhalb des Packages.
Tipp: Wenn Sie eine PL/SQL-Variable in einer SQL-Anweisung verwenden, wie in der zweiten SELECT-Anweisung in Beispiel 5-4, qualifizieren Sie die Variable mit dem Unterprogrammnamen, um sicherzustellen, dass sie nicht mit einer Tabellenspalte verwechselt wird.
Siehe:
-
Oracle Database PL/SQL Language Reference für die Syntax der IF-Anweisung
-
Oracle Database PL/SQL Language Reference, um weitere Informationen zur Verwendung der IF-Anweisung zu finden
Beispiel 5-4: IF-Anweisung bestimmt den Rückgabewert der Funktion
FUNCTION eval_frequency (emp_id IN EMPLOYEES.EMPLOYEE_ID%TYPE)
RETURN PLS_INTEGER
AS
h_date EMPLOYEES.HIRE_DATE%TYPE;
today EMPLOYEES.HIRE_DATE%TYPE;
eval_freq PLS_INTEGER;
BEGIN
SELECT SYSDATE INTO today FROM DUAL;
SELECT HIRE_DATE INTO h_date
FROM EMPLOYEES
WHERE EMPLOYEE_ID = eval_frequency.emp_id;
IF ((h_date + (INTERVAL '120' MONTH)) < today) THEN
eval_freq := 1;
ELSE
eval_freq := 2;
END IF;
RETURN eval_freq;
END eval_frequency;
CASE-Ausdruck verwenden
Die CASE-Anweisung trifft eine Wahl aus einer Bedingungssequenz und führt die entsprechende Anweisung durch.
Mit der einfachen CASE-Anweisung wird ein einzelner Ausdruck ausgewertet und mit mehreren potenziellen Werten verglichen. Die Anweisung hat folgende Syntax:
CASE expression
WHEN value THEN statement
[ WHEN value THEN statement ]...
[ ELSE statement [, statement ]... ]
END CASE;
Die gesuchte CASE-Anweisung bewertet mehrere boolesche Ausdrücke und wählt den ersten, dessen Wert TRUE ist. Weitere Informationen zur gesuchten CASE-Anweisung finden Sie unter Oracle Database PL/SQL Language Reference.
Tipp: Wenn Sie entweder eine CASE-Anweisung oder verschachtelte IF-Anweisungen verwenden können, verwenden Sie die CASE-Anweisung, da sie leichter lesbar und effizienter ist.
Nehmen wir an, dass ein Mitarbeiter einmal pro Jahr evaluiert wird, und Sie möchten die Funktion EVAL_FREQUENCY eine Gehaltserhöhung vorschlagen, die an die JOB_ID gekoppelt ist.
Ändern Sie die Funktion EVAL_FREQUENCY wie in Beispiel 5-5 gezeigt. (Informationen zu den Zeichenfolgen gedruckt werden, DBMS_OUTPUT.PUT_LINE erhalten Sie unter Oracle Database PL/SQL Packages and Types Reference.)
Beispiel 5-5: CASE-Anweisung, die bestimmt, welche Zeichenfolge gedruckt werden soll
FUNCTION eval_frequency (emp_id IN EMPLOYEES.EMPLOYEE_ID%TYPE)
RETURN PLS_INTEGER
AS
h_date EMPLOYEES.HIRE_DATE%TYPE;
today EMPLOYEES.HIRE_DATE%TYPE;
eval_freq PLS_INTEGER;
j_id EMPLOYEES.JOB_ID%TYPE;
BEGIN
SELECT SYSDATE INTO today FROM DUAL;
SELECT HIRE_DATE, JOB_ID INTO h_date, j_id
FROM EMPLOYEES
WHERE EMPLOYEE_ID = eval_frequency.emp_id;
IF ((h_date + (INTERVAL '12' MONTH)) < today) THEN
eval_freq := 1;
CASE j_id
WHEN 'PU_CLERK' THEN DBMS_OUTPUT.PUT_LINE(
'Consider 8% salary increase for employee # ' || emp_id);
WHEN 'SH_CLERK' THEN DBMS_OUTPUT.PUT_LINE(
'Consider 7% salary increase for employee # ' || emp_id);
WHEN 'ST_CLERK' THEN DBMS_OUTPUT.PUT_LINE(
'Consider 6% salary increase for employee # ' || emp_id);
WHEN 'HR_REP' THEN DBMS_OUTPUT.PUT_LINE(
'Consider 5% salary increase for employee # ' || emp_id);
WHEN 'PR_REP' THEN DBMS_OUTPUT.PUT_LINE(
'Consider 5% salary increase for employee # ' || emp_id);
WHEN 'MK_REP' THEN DBMS_OUTPUT.PUT_LINE(
'Consider 4% salary increase for employee # ' || emp_id);
ELSE DBMS_OUTPUT.PUT_LINE(
'Nothing to do for employee #' || emp_id);
END CASE;
ELSE
eval_freq := 2;
END IF;
RETURN eval_freq;
END eval_frequency;
Siehe:
-
Oracle Database PL/SQL Language Reference für die Syntax der CASE-Anweisung
-
Oracle Database PL/SQL Language Reference für weitere Informationen über die Verwendung der CASE-Anweisung
"FOR LOOP"-Anweisung verwenden
Mit der Anweisung FOR LOOP wird eine Anweisungssequenz jeweils eine Mal pro Ganzzahl im Bereich lower_bound bis upper_bound wiederholt.
Die Syntax des FOR LOOP lautet:
FOR counter IN lower_bound..upper_bound LOOP
statement [, statement ]...
END LOOP;
Die Anweisungen zwischen LOOP und END LOOP können Zähler verwenden, den Wert jedoch nicht ändern.
Nehmen wir an, Sie möchten, dass Ihnen die Funktion EVAL_FREQUENCY nicht nur eine Gehaltserhöhung vorschlägt, sondern auch mitteilt, wie das Gehalt aussähe, wenn es fünf Jahre lang jedes Jahr um den vorgeschlagenen Betrag erhöht würde.
Ändern Sie die Funktion EVAL_FREQUENCY wie in Beispiel 5-6 gezeigt. (Informationen zu dem Verfahren, über das die Zeichenfolgen gedruckt werden, DBMS_OUTPUT.PUT_LINE, finden Sie unter Oracle Database PL/SQL Packages and Types Reference.)
Beispiel 5-6: FOR LOOP-Anweisung, über die das Gehalt nach fünf Jahren berechnet wird
FUNCTION eval_frequency (emp_id IN EMPLOYEES.EMPLOYEE_ID%TYPE)
RETURN PLS_INTEGER
AS
h_date EMPLOYEES.HIRE_DATE%TYPE;
today EMPLOYEES.HIRE_DATE%TYPE;
eval_freq PLS_INTEGER;
j_id EMPLOYEES.JOB_ID%TYPE;
sal EMPLOYEES.SALARY%TYPE;
sal_raise NUMBER(3,3) := 0;
BEGIN
SELECT SYSDATE INTO today FROM DUAL;
SELECT HIRE_DATE, JOB_ID, SALARY INTO h_date, j_id, sal
FROM EMPLOYEES
WHERE EMPLOYEE_ID = eval_frequency.emp_id;
IF ((h_date + (INTERVAL '12' MONTH)) < today) THEN
eval_freq := 1;
CASE j_id
WHEN 'PU_CLERK' THEN sal_raise :=
0.08;
WHEN 'SH_CLERK' THEN sal_raise := 0.07;
WHEN 'ST_CLERK' THEN sal_raise := 0.06;
WHEN 'HR_REP' THEN sal_raise := 0.05;
WHEN 'PR_REP' THEN sal_raise := 0.05;
WHEN 'MK_REP' THEN sal_raise := 0.04;
ELSE NULL;
END CASE;
IF (sal_raise != 0) THEN
BEGIN
DBMS_OUTPUT.PUT_LINE('If salary ' || sal || ' increases by ' ||
ROUND((sal_raise * 100),0) ||
'% each year for 5 years, it will be:');
FOR i IN 1..5 LOOP
sal := sal * (1 + sal_raise);
DBMS_OUTPUT.PUT_LINE(ROUND(sal, 2) || ' after ' || i || ' year(s)');
END LOOP;
END;
END IF;
ELSE
eval_freq := 2;
END IF;
RETURN eval_freq;
END eval_frequency;
Siehe:
-
Oracle Database PL/SQL Language Reference für die Syntax der Anweisung FOR LOOP
-
Oracle Database PL/SQL Language Reference für weitere Informationen über die Verwendung der Anweisung FOR LOOP
"WHILE LOOP"-Anweisung verwenden
Mit der Anweisung WHILE LOOP wird eine Reihe von Anweisungen wiederholt, solange eine Bedingung TRUE ist.
Die Syntax der WHILE LOOP-Anweisung lautet:
WHILE condition LOOP
statement [, statement ]...
END LOOP;
Hinweis: Wenn die Anweisungen zwischen LOOP und END LOOP nie dazu führen, dass die Bedingung FALSE wird, wird die Anweisung WHILE LOOP endlos ausgeführt.
Angenommen, die Funktion EVAL_FREQUENCY verwendet die Anweisung WHILE LOOP anstelle der Anweisung FOR LOOP und endet, nachdem das vorgeschlagene Gehalt das Maximalgehalt der JOB_ID übersteigt.
Ändern Sie die Funktion EVAL_FREQUENCY wie in Beispiel 5-7 gezeigt. (Informationen zu den Zeichenfolgen gedruckt werden, DBMS_OUTPUT.PUT_LINE erhalten Sie unter Oracle Database PL/SQL Packages and Types Reference.)
Beispiel 5-7 WHILE LOOP-Anweisung zur Berechnung von Gehalt bis Maximum
FUNCTION eval_frequency (emp_id IN EMPLOYEES.EMPLOYEE_ID%TYPE)
RETURN PLS_INTEGER
AS
h_date EMPLOYEES.HIRE_DATE%TYPE;
today EMPLOYEES.HIRE_DATE%TYPE;
eval_freq PLS_INTEGER;
j_id EMPLOYEES.JOB_ID%TYPE;
sal EMPLOYEES.SALARY%TYPE;
sal_raise NUMBER(3,3) := 0;
sal_max JOBS.MAX_SALARY%TYPE;
BEGIN
SELECT SYSDATE INTO today FROM DUAL;
SELECT HIRE_DATE, j.JOB_ID, SALARY, MAX_SALARY INTO h_date, j_id, sal, sal_max
FROM EMPLOYEES e, JOBS j
WHERE EMPLOYEE_ID = eval_frequency.emp_id AND JOB_ID = eval_frequency.j_id;
IF ((h_date + (INTERVAL '12' MONTH)) < today) THEN
eval_freq := 1;
CASE j_id
WHEN 'PU_CLERK' THEN sal_raise := 0.08;
WHEN 'SH_CLERK' THEN sal_raise := 0.07;
WHEN 'ST_CLERK' THEN sal_raise := 0.06;
WHEN 'HR_REP' THEN sal_raise := 0.05;
WHEN 'PR_REP' THEN sal_raise := 0.05;
WHEN 'MK_REP' THEN sal_raise := 0.04;
ELSE NULL;
END CASE;
IF (sal_raise != 0) THEN
BEGIN
DBMS_OUTPUT.PUT_LINE('If salary ' || sal || ' increases by ' ||
ROUND((sal_raise * 100),0) ||
'% each year, it will be:');
WHILE sal <= sal_max LOOP
sal := sal * (1 + sal_raise);
DBMS_OUTPUT.PUT_LINE(ROUND(sal, 2));
END LOOP;
DBMS_OUTPUT.PUT_LINE('Maximum salary for this job is ' || sal_max);
END;
END IF;
ELSE
eval_freq := 2;
END IF;
RETURN eval_freq;
END eval_frequency;
Siehe:
-
Oracle Database PL/SQL-Sprachreferenz für die Syntax der Anweisung WHILE LOOP
-
Oracle Database PL/SQL Language Reference für weitere Informationen über die Verwendung der Anweisung WHILE LOOP
"Basic LOOP"- und "EXIT WHEN"-Anweisungen verwenden
Die grundlegende Anweisung LOOP wiederholt eine Sequenz von Anweisungen.
Die Syntax der grundlegenden LOOP-Anweisung lautet:
LOOP
statement [, statement ]...
END LOOP;
Mindestens eine Anweisung muss eine EXIT-Anweisung sein. Andernfalls wird die LOOP-Anweisung unbegrenzt ausgeführt.
Die Anweisung EXIT WHEN (die Anweisung EXIT mit der optionalen WHEN-Klausel) verlässt eine Schleife, wenn eine Bedingung TRUE ist und an das Ende der Schleife überträgt.
In der Funktion EVAL_FREQUENCY übersteigt während der letzten Wiederholung der WHILE LOOP-Anweisung der letzte berechnete Wert normalerweise das Höchstgehalt.
Ändern Sie die Anweisung WHILE LOOP in eine grundlegende LOOP-Anweisung mit der Anweisung EXIT WHEN, wie in Beispiel 5-8.
Beispiel 5-8: EXIT WHEN-Anweisung verwenden
FUNCTION eval_frequency (emp_id IN EMPLOYEES.EMPLOYEE_ID%TYPE)
RETURN PLS_INTEGER
AS
h_date EMPLOYEES.HIRE_DATE%TYPE;
today EMPLOYEES.HIRE_DATE%TYPE;
eval_freq PLS_INTEGER;
j_id EMPLOYEES.JOB_ID%TYPE;
sal EMPLOYEES.SALARY%TYPE;
sal_raise NUMBER(3,3) := 0;
sal_max JOBS.MAX_SALARY%TYPE;
BEGIN
SELECT SYSDATE INTO today FROM DUAL;
SELECT HIRE_DATE, j.JOB_ID, SALARY, MAX_SALARY INTO h_date, j_id, sal, sal_max
FROM EMPLOYEES e, JOBS j
WHERE EMPLOYEE_ID = eval_frequency.emp_id AND JOB_ID = eval_frequency.j_id;
IF ((h_date + (INTERVAL '12' MONTH)) < today) THEN
eval_freq := 1;
CASE j_id
WHEN 'PU_CLERK' THEN sal_raise := 0.08;
WHEN 'SH_CLERK' THEN sal_raise := 0.07;
WHEN 'ST_CLERK' THEN sal_raise := 0.06;
WHEN 'HR_REP' THEN sal_raise := 0.05;
WHEN 'PR_REP' THEN sal_raise := 0.05;
WHEN 'MK_REP' THEN sal_raise := 0.04;
ELSE NULL;
END CASE;
IF (sal_raise != 0) THEN
BEGIN
DBMS_OUTPUT.PUT_LINE('If salary ' || sal || ' increases by ' ||
ROUND((sal_raise * 100),0) ||
'% each year, it will be:');
LOOP
sal := sal * (1 + sal_raise);
EXIT WHEN sal > sal_max;
DBMS_OUTPUT.PUT_LINE(ROUND(sal,2));
END LOOP;
DBMS_OUTPUT.PUT_LINE('Maximum salary for this job is ' || sal_max);
END;
END IF;
ELSE
eval_freq := 2;
END IF;
RETURN eval_freq;
END eval_frequency;
Siehe:
-
Oracle Database PL/SQL Language Reference für die Syntax der LOOP-Anweisung
-
Oracle Database PL/SQL Language Reference für die Syntax der Anweisung EXIT
-
Weitere Informationen zur Verwendung der Anweisungen LOOP und EXIT finden Sie in Oracle Database PL/SQL Language Reference.