Flux du programme de contrôle
Contrairement à SQL, qui exécute des instructions dans l'ordre dans lequel vous les entrez, PL/SQL comporte des instructions de contrôle qui vous permettent de contrôler le flux de votre programme.
À propos des énoncés de contrôle
Le langage PL/SQL comprend trois catégories d'instructions de contrôle : les instructions de sélection conditionnelle, les instructions de boucle et les instructions de contrôle séquentielles.
Les énoncés de sélection conditionnels vous permettent d'exécuter différents énoncés pour différentes valeurs de données. Les énoncés de sélection conditionnelle sont IF et CASE.
Les énoncés en boucle vous permettent de répéter les mêmes énoncés avec une série de valeurs de données différentes. Les énoncés de boucle sont FOR LOOP, WHILE LOOP et LOOP de base. L'énoncé EXIT transfère le contrôle à la fin d'une boucle. L'énoncé CONTINUE quitte l'itération courante d'une boucle et transfère le contrôle à l'itération suivante. EXIT et CONTINUE comportent une clause WHEN facultative, dans laquelle vous pouvez spécifier une condition.
Les énoncés de contrôle séquentiel vous permettent d'accéder à un énoncé étiqueté spécifié ou de ne rien faire. Les énoncés de contrôle séquentiels sont GOTO et NULL.
Voir aussi : Informations de référence sur le langage PL/SQL pour Oracle Database pour un aperçu des énoncés de contrôle PL/SQL
Utiliser l'instruction IF
L'instruction IF exécute ou ignore une séquence d'instructions, selon la valeur d'une expression booléenne.
L'instruction IF comporte la syntaxe suivante :
IF boolean_expression THEN statement [, statement ]
[ ELSIF boolean_expression THEN statement [, statement ] ]...
[ ELSE statement [, statement ] ]
END IF;
Supposons que votre société évalue les employés deux fois par an au cours des 10 premières années d'emploi, mais seulement une fois par an après. Vous voulez une fonction qui retourne la fréquence d'évaluation d'un employé. Vous pouvez utiliser un énoncé IF pour déterminer la valeur de retour de la fonction, comme dans Exemple 5-4.
Ajoutez la fonction EVAL_FREQUENCY au corps du package EMP_EVAL, mais pas à la spécification. Comme ce n'est pas dans la spécification, EVAL_FREQUENCY est local au package. Il ne peut être appelé que par d'autres sous-programmes du package, et non par l'extérieur du package.
Conseil : Lorsque vous utilisez une variable PL/SQL dans un énoncé SQL, comme dans le deuxième énoncé SELECT de l'exemple 5-4, qualifiez la variable avec le nom du sous-programme pour vous assurer qu'elle n'est pas prise par erreur pour une colonne de table.
Voir aussi :
-
Informations de référence sur le langage PL/SQL pour Oracle Database pour la syntaxe de l'énoncé IF
-
Informations de référence sur le langage PL/SQL pour Oracle Database pour plus d'informations sur l'utilisation de l'énoncé IF
Exemple 5-4 : Instruction IF qui détermine la valeur renvoyée de la fonction
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;
Utilisation de l'instruction CASE
L'instruction CASE choisit une séquence de conditions et exécute l'instruction correspondante.
L'instruction simple CASE évalue une seule expression et la compare à plusieurs valeurs potentielles. Il a cette syntaxe :
CASE expression
WHEN value THEN statement
[ WHEN value THEN statement ]...
[ ELSE statement [, statement ]... ]
END CASE;
L'instruction CASE recherchée évalue plusieurs expressions booléennes et choisit la première dont la valeur est TRUE. Pour plus d'informations sur l'énoncé CASE recherché, voir Informations de référence sur le langage PL/SQL pour Oracle Database.
Conseil : Lorsque vous pouvez utiliser un énoncé CASE ou IF imbriqué, utilisez un énoncé CASE-il est à la fois plus lisible et plus efficace.
Supposons que, si un employé n'est évalué qu'une fois par an, vous souhaitez que la fonction EVAL_FREQUENCY suggère une augmentation de salaire, qui dépend de la valeur JOB_ID.
Modifiez la fonction EVAL_FREQUENCY comme indiqué dans Exemple 5-5. (Pour plus d'informations sur les procédures qui impriment les chaînes, DBMS_OUTPUT.PUT_LINE, voir Informations de référence sur les ensembles et les types PL/SQL pour Oracle Database.)
Exemple 5-5 : Énoncé CASE qui détermine la chaîne à imprimer
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;
Voir aussi :
-
Informations de référence sur le langage PL/SQL pour Oracle Database pour la syntaxe de l'énoncé CASE
-
Informations de référence sur le langage PL/SQL pour Oracle Database pour plus d'informations sur l'utilisation de l'énoncé CASE
Utilisation de l'instruction FOR LOOP
L'instruction FOR LOOP répète une séquence d'instructions une fois pour chaque entier de l'intervalle lower_bound via upper_bound.
La syntaxe de FOR LOOP est la suivante :
FOR counter IN lower_bound..upper_bound LOOP
statement [, statement ]...
END LOOP;
Les instructions entre LOOP et END LOOP peuvent utiliser un compteur, mais ne peuvent pas modifier sa valeur.
Supposons qu'au lieu de suggérer seulement une augmentation de salaire, vous vouliez que la fonction EVAL_FREQUENCY signale ce que serait le salaire s'il était augmenté du montant suggéré chaque année pendant cinq ans.
Modifiez la fonction EVAL_FREQUENCY comme indiqué dans Exemple 5-6. (Pour plus d'informations sur la procédure d'impression des chaînes, DBMS_OUTPUT.PUT_LINE, voir Informations de référence sur les ensembles et les types PL/SQL pour Oracle Database.)
Exemple 5-6 : Énoncé de congé qui calcule le salaire après cinq ans
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;
Voir aussi :
-
Informations de référence sur le langage PL/SQL pour Oracle Database pour la syntaxe de l'énoncé FOR LOOP
-
Informations de référence sur le langage PL/SQL pour Oracle Database pour plus d'informations sur l'utilisation de l'énoncé FOR LOOP
Utilisation de l'instruction WHILE LOOP
L'instruction WHILE LOOP répète une séquence d'instructions alors qu'une condition est TRUE.
La syntaxe de l'instruction WHILE LOOP est la suivante :
WHILE condition LOOP
statement [, statement ]...
END LOOP;
Note : Si les énoncés entre LOOP et END LOOP ne causent jamais la condition FALSE, l'énoncé WHILE LOOP s'exécute indéfiniment.
Supposons que la fonction EVAL_FREQUENCY utilise l'instruction WHILE LOOP au lieu de l'instruction FOR LOOP et se termine après que le salaire proposé dépasse le salaire maximum pour JOB_ID.
Modifiez la fonction EVAL_FREQUENCY comme indiqué dans Exemple 5-7. (Pour plus d'informations sur les procédures qui impriment les chaînes, DBMS_OUTPUT.PUT_LINE, voir Informations de référence sur les ensembles et les types PL/SQL pour Oracle Database.)
Exemple 5-7 : Énoncé WHILE LOOP qui calcule le salaire jusqu'au 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;
Voir aussi :
-
Informations de référence sur le langage PL/SQL pour Oracle Database pour la syntaxe de l'énoncé WHILE LOOP
-
Informations de référence sur le langage PL/SQL pour Oracle Database pour plus d'informations sur l'utilisation de l'énoncé WHILE LOOP
Utilisation des instructions Basic LOOP et EXIT WHEN
L'instruction LOOP de base répète une séquence d'instructions.
La syntaxe de l'instruction LOOP de base est la suivante :
LOOP
statement [, statement ]...
END LOOP;
Au moins une instruction doit être une instruction EXIT; sinon, l'instruction LOOP s'exécute indéfiniment.
L'instruction EXIT WHEN (l'instruction EXIT avec sa clause WHEN facultative) quitte une boucle lorsqu'une condition est TRUE et transfère le contrôle à la fin de la boucle.
Dans la fonction EVAL_FREQUENCY, lors de la dernière itération de l'instruction WHILE LOOP, la dernière valeur calculée dépasse généralement le salaire maximum.
Remplacez l'énoncé WHILE LOOP par un énoncé LOOP de base qui inclut un énoncé EXIT WHEN, comme dans l'exemple 5-8.
Exemple 5-8 : Utiliser l'instruction EXIT WHEN
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;
Voir aussi :
-
Informations de référence sur le langage PL/SQL pour Oracle Database pour la syntaxe de l'énoncé LOOP
-
Informations de référence sur le langage PL/SQL pour Oracle Database pour la syntaxe de l'énoncé EXIT
-
Informations de référence sur le langage PL/SQL pour Oracle Database pour plus d'informations sur l'utilisation des énoncés LOOP et EXIT