Utilisation des enregistrements et des curseurs
Le contenu du script de cette page a pour seul objectif la navigation et n'altère en rien le contenu.
Vous pouvez stocker des valeurs de données dans des enregistrements et utiliser un curseur comme pointeur vers un ensemble de résultats et des informations de traitement associées.
Voir aussi : Oracle Database PL/SQL Language Reference, pour plus d'informations sur les enregistrements.
A propos des enregistrements
Un enregistrement est une variable composite PL/SQL qui peut stocker des valeurs de données de différents types. Vous pouvez traiter les composants internes (champs) comme des variables scalaires. Vous pouvez transmettre des enregistrements entiers en tant que paramètres de sous-programme. Les enregistrements peuvent contenir des données issues de lignes de table ou de certaines colonnes des lignes de table.
Un enregistrement est une variable composite PL/SQL pouvant stocker des valeurs de données de différents types, semblable à un type de structure en C, C++ ou Java. Les composants internes d'un enregistrement sont appelés champs. Pour accéder à un champ d'enregistrement, utilisez la notation par points : record_name.field_name.
Les champs d'enregistrements peuvent être traités comme des variables scalaires. Vous pouvez également transmettre des enregistrements entiers en tant que paramètres de sous-programme.
Les enregistrements peuvent contenir des données issues de lignes de table ou de certaines colonnes des lignes de table. Chaque champ d'enregistrement correspond à une colonne de table.
Vous pouvez créer un enregistrement de trois façons :
-
Déclarez un type RECORD, puis déclarez une variable de ce type.
Utilisez la syntaxe suivante :
TYPE record_name IS RECORD ( field_name data_type [:= initial_value] [, field_name data_type [:= initial_value ] ]... ); variable_name record_name; -
Déclarez une variable du type table_name%ROWTYPE.
Les champs de l'enregistrement présentent les mêmes noms et types de données que les colonnes de la table.
-
Déclarez une variable du type Curseur_Nom%ROWTYPE.
Les champs de l'enregistrement présentent les mêmes noms et types d'informations que les colonnes de la table dans la clause FROM de l'instruction SELECT du curseur.
Voir aussi :
-
Manuel Oracle Database PL/SQL Language Reference, pour plus d'informations sur l'établissement des types RECORD et l'enregistrement de ce type.
-
Manuel Oracle Database PL/SQL Language Reference, pour connaitre la syntaxe d'une définition du type RECORD
-
Manuel Oracle Database PL/SQL Language Reference, pour plus d'informations sur l'attribut %ROWTYPE
-
Manuel Oracle Database PL/SQL Language Reference, pour en savoir plus sur la syntaxe de l'attribut %ROWTYPE
Tutoriel : Déclaration d'un type RECORD
The following steps show how to use the SQL Developer tool Edit to declare a RECORD type, sal_info, whose fields can hold salary information for an employee—job ID, minimum and maximum salary for that job ID, current salary, and suggested raise.
Etapes de déclaration du type RECORD sal_info :
-
Dans le cadre Connexions, développez hr_conn.
Sous l'icône hr_conn, la liste des types d'objet de schéma apparaît.
-
Développez Packages.
La liste des packages apparaît.
-
Cliquez sur EMP_EVAL avec le bouton droit de la souris.
La liste des options apparaît.
-
Sélectionnez Modifier.
Le panneau EMP_EVAL apparaît et affiche l'instruction
CREATE PACKAGEayant créé le package :CREATE OR REPLACE PACKAGE EMP_EVAL AS PROCEDURE eval_department(dept_id IN NUMBER); FUNCTION calculate_score(evaluation_id IN NUMBER , performance_id IN NUMBER) RETURN NUMBER; END EMP_EVAL; -
Dans le panneau EMP_EVAL, juste avant
END EMP_EVAL, ajoutez Le code suivant :TYPE sal_info IS RECORD ( j_id jobs.job_id%type , sal_min jobs.min_salary%type , sal_max jobs.max_salary%type , sal employees.salary%type , sal_raise NUMBER(3,3) );Le titre du panneau apparaît en italique, afin d'indiquer que les modifications ne sont pas enregistrées sur la base de données.
-
Sélectionnez l'icône Compiler.
La spécification de package modifiée est compilée et enregistrée dans la base de données. Le titre du panneau EMP_EVAL n'apparaît plus en italique.
Vous pouvez désormais déclarer des enregistrements du type sal_info, comme dans la rubrique "Tutorial : Creating and Invoking a Subprogram with a Record Parameter".
Tutoriel : Création et appel d'un sous-programme avec un paramètre d'enregistrement
Les étapes suivantes montrent comment utiliser l'outil SQL Developer Modifier pour créer et appeler un sous-programme avec un paramètre de type d'enregistrement sal_info.
Le type d'enregistrement sal_info a été créé dans "Tutoriel : Déclaration d'un type d'enregistrement".
Ce tutoriel indique comment utiliser l'outil SQL Developer Modifier pour effectuer les tâches suivantes :
-
Créer une procédure nommée SALARY_SCHEDULE qui dispose d'un paramètre de type
sal_info. -
Modifier la fonction EVAL_FREQUENCY pour qu'elle déclare un enregistrement nommé emp_sal du type
sal_info, qu'elle remplisse les champs pour les transmette à la procédure SALARY_SCHEDULE.
Puisque EVAL_FREQUENCY invoquera SALARY_SCHEDULE, la déclaration de SALARY_SCHEDULE doit être antérieure à celle de EVAL_FREQUENCY (sinon, le package ne pourra pas été compilé). Toutefois, la définition de SALARY_SCHEDULE peut figurer à n'importe quel endroit du corps du package.
Etapes de création de SALARY_SCHEDULE et de modification de EVAL_FREQUENCY :
-
Dans le cadre Connexions, développez hr_conn.
-
Dans la liste des types d'objet de schéma, développez Packages.
-
Dans la liste des packages, développez EMP_EVAL.
-
Dans la liste des choix, cliquez avec le bouton droit de la souris sur Corps EVAL_EMP.
-
Dans la liste des choix, sélectionnez Modifier.
Le panneau Corps EMP_EVAL apparaît avec le code du corps du package.
-
Dans le panneau EMP_EVAL Body, juste avant
END EMP_EVAL, ajoutez l'expression suivante de la procédure SALARY_SCHEDULE :PROCEDURE salary_schedule (emp IN sal_info) AS accumulating_sal NUMBER; BEGIN DBMS_OUTPUT.PUT_LINE('If salary ' || emp.sal || ' increases by ' || ROUND((emp.sal_raise * 100),0) || '% each year, it will be:'); accumulating_sal := emp.sal; WHILE accumulating_sal <= emp.sal_max LOOP accumulating_sal := accumulating_sal * (1 + emp.sal_raise); DBMS_OUTPUT.PUT_LINE(ROUND(accumulating_sal,2) ||', '); END LOOP; END salary_schedule;Le titre du panneau apparaît en italique, afin d'indiquer que les modifications ne sont pas enregistrées sur la base de données.
-
Dans le volet Corps EMP_EVAL, saisissez la fonction eval_frequency et les procédures salary_schedule et add_eval à la position suivante :
CREATE OR REPLACE PACKAGE BODY EMP_EVAL AS FUNCTION eval_frequency (emp_id EMPLOYEES.EMPLOYEE_ID%TYPE) RETURN PLS_INTEGER; PROCEDURE salary_schedule(emp IN sal_info); PROCEDURE add_eval(employee_id IN employees.employee_id%type, today IN DATE); PROCEDURE eval_department (dept_id IN NUMBER) AS -
Modifiez la fonction
EVAL_FREQUENCYen procédant comme suit :FUNCTION eval_frequency (emp_id EMPLOYEES.EMPLOYEE_ID%TYPE) RETURN PLS_INTEGER AS h_date EMPLOYEES.HIRE_DATE%TYPE; today EMPLOYEES.HIRE_DATE%TYPE; eval_freq PLS_INTEGER; emp_sal SAL_INFO; -- replaces sal, sal_raise, and sal_max 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; /* populate emp_sal */ SELECT j.JOB_ID, j.MIN_SALARY, j.MAX_SALARY, e.SALARY INTO emp_sal.j_id, emp_sal.sal_min, emp_sal.sal_max, emp_sal.sal FROM EMPLOYEES e, JOBS j WHERE e.EMPLOYEE_ID = eval_frequency.emp_id AND j.JOB_ID = eval_frequency.emp_id; emp_sal.sal_raise := 0; -- default CASE emp_sal.j_id WHEN 'PU_CLERK' THEN emp_sal.sal_raise := 0.08; WHEN 'SH_CLERK' THEN emp_sal.sal_raise := 0.07; WHEN 'ST_CLERK' THEN emp_sal.sal_raise := 0.06; WHEN 'HR_REP' THEN emp_sal.sal_raise := 0.05; WHEN 'PR_REP' THEN emp_sal.sal_raise := 0.05; WHEN 'MK_REP' THEN emp_sal.sal_raise := 0.04; ELSE NULL; END CASE; IF (emp_sal.sal_raise != 0) THEN salary_schedule(emp_sal); END IF; ELSE eval_freq := 2; END IF; RETURN eval_freq; END eval_frequency; -
Sélectionnez Compiler.
A propos des curseurs
Lorsqu'Oracle Database exécute une instruction SQL, il stocke l'ensemble de résultats et les informations de traitement dans une zone SQL privée sans nom. Un pointeur vers cette zone sans nom, appelé curseur, permet d'extraire l'ensemble de résultats ligne par ligne. Les attributs du Curseur renvoient des informations concernant l'état du Curseur.
Chaque fois que vous exécutez une instruction SQL DML ou une instruction PL/SQL SELECT INTO, PL/SQL ouvre un curseur implicite. Vous pouvez obtenir des informations sur ce curseur à l'aide de ses attributs, mais vous ne pouvez pas le contrôler. Après l'exécution de l'instruction, la base de données ferme le curseur. Toutefois, ses valeurs d'attribut restent disponibles jusqu'à l'exécution d'une autre instruction DML ou SELECT INTO.
Le langage PL/SQL permet également de déclarer des curseurs. Un curseur déclaré porte un nom et est associé à une requête (instruction SQL SELECT), qui renvoie généralement plusieurs lignes. Après avoir déclaré un curseur, vous devez le traiter, implicitement ou explicitement. Pour traiter le curseur implicitement, utilisez un curseur FOR LOOP. La syntaxe est la suivante :
FOR record_name IN cursor_name LOOP
statement
[ statement ]...
END LOOP;
Pour traiter explicitement le curseur, ouvrez-le (avec l'instruction OPEN), extrayez les lignes de l'ensemble de résultats une par une ou en masse (avec l'instruction FETCH) et fermez le curseur (avec l'instruction CLOSE). Suite à la fermeture du curseur, vous ne pouvez plus extraire les enregistrements de l'ensemble de résultats, ni visualiser les valeurs des attributs du curseur.
La valeur d'un attribut de curseur implicite est SQL%attribute (par exemple, SQL%FOUND). SQL%attribute fait toujours référence à la toute dernière instruction DML ou SELECT INTO exécutée.
La valeur d'un attribut de curseur déclaré respecte la syntaxe curseur_name%attribute (par exemple, c1%FOUND). Le tableau 1 dresse la liste des attributs de curseurs et des valeurs qu'ils peuvent renvoyer. (Les curseurs implicites disposent d'attributs supplémentaires non traités par le présent manuel.)
Table 1 - Valeurs d'attribut de curseur
| Attribut | Valeurs pour le curseur déclaré | Valeurs pour un curseur implicite |
|---|---|---|
| %TROUVÉ | Si le curseur est ouvert (note de bas de page 1) sans tentative d'extraction, NULL. Si la dernière extraction a renvoyé une ligne, TRUE. Si la dernière extraction n'a renvoyé pas de ligne, FALSE. |
Si aucune instruction SELECT INTO ou DML n'a été exécutée, NULL. Si la dernière instruction DML ou SELECT INTO a renvoyé une ligne, TRUE. Si la dernière instruction DML ou SELECT INTO n'a renvoyé pas de ligne, FALSE. |
| %INTROUVABLE | Si le curseur est ouvert (note de bas de page 1) sans tentative d'extraction, NULL. Si la dernière extraction a renvoyé une ligne, FALSE. Si la dernière extraction n'a renvoyé pas de ligne, TRUE. |
Si aucune instruction SELECT INTO ou DML n'a été exécutée, NULL. Si la dernière instruction SELECT INTO ou DML a renvoyé une ligne, Si la dernière instruction DML ou SELECT INTO n'a renvoyé pas de ligne, |
| %NOMBRE DE LIGNES | Si le curseur est ouvert (note de bas de page 1), un nombre supérieur ou égal à zéro. | NULL si aucune instruction DML ou SELECT INTO n'a été exécutée ; sinon, un nombre supérieur ou égal à zéro. |
| % OUVERT | Si le curseur est ouvert, TRUE ; sinon, FALSE. | Toujours FALSE. |
Note de bas de page 1 : si le curseur n'est pas ouvert, l'attribut génère l'exception prédéfinie INVALID_CURSOR.
Voir aussi :
-
Oracle Database PL/SQL Language Reference, pour plus d'informations sur l'instruction SELECT INTO
-
Oracle Database PL/SQL Language Reference, pour plus d'informations sur la gestion des curseurs dans PL/SQL
Utilisation d'un curseur déclaré pour extraire les lignes d'un ensemble de résultats, une à la fois
Vous pouvez utiliser un curseur déclaré pour extraire les lignes d'ensemble de résultats une par une.
La procédure suivante utilise chaque instruction nécessaire dans sa forme la plus simple, mais fournit les références correspondantes avec la syntaxe complète.
Etapes à suivre pour utiliser un curseur déclaré afin d'extraire les lignes d'ensemble de résultats une par une :
-
Dans la partie de déclaration, effectuez les opérations suivantes :
-
Déclarez le curseur :
CURSOR cursor_name IS query;Pour connaître la syntaxe complète des déclarations de curseurs déclarés, reportez-vous à Oracle Database PL/SQL Language Reference.
-
Déclarez un enregistrement pouvant contenir la ligne renvoyée par le curseur :
record_name cursor_name%ROWTYPE;Pour connaître la syntaxe complète de %ROWTYPE, reportez-vous au guide Oracle Database PL/SQL Language Reference.
-
-
Dans la partie d'exécution, effectuez les opérations suivantes :
-
Ouvrez le curseur :
OPEN cursor_name;Pour connaître la syntaxe complète de l'instruction OPEN, reportez-vous au guide Oracle Database PL/SQL Language Reference.
-
Extrayez, une par une, les lignes du curseur (lignes de l'ensemble de résultats) à l'aide d'une instruction LOOP dont le code est semblable à celui qui suit :
LOOP FETCH cursor_name INTO record_name; EXIT WHEN cursor_name%NOTFOUND; -- Process row that is in record_name: statement; [ statement; ]... END LOOP;Pour connaître la syntaxe complète de l'instruction FETCH, reportez-vous au guide Oracle Database PL/SQL Language Reference.
-
Fermez le curseur :
CLOSE cursor_name;
-
Pour connaître la syntaxe complète de l'instruction CLOSE, reportez-vous au guide Oracle Database PL/SQL Language Reference.
Tutoriel : Utilisation d'un curseur de curseur pour extraire les lignes de l' ensemble de résultats, une à la fois
Les étapes suivantes montrent comment implémenter la procédure EMP_EVAL.EVAL_DEPARTMENT, qui utilise un curseur déclaré, emp_cursor.
Pour implémenter la procédure EMP_EVAL.EVAL_DEPARTMENT, procédez comme suit :
-
Dans la spécification de package EMP_EVAL, modifiez la déclaration de la procédure EVAL_DEPARTMENT comme indiqué :
PROCEDURE eval_department(dept_id IN employees.department_id%TYPE); -
Dans le corps de package EMP_EVAL, modifiez la définition de la procédure EVAL_DEPARTMENT comme indiqué en caractères gras dans l'exemple suivant :
PROCEDURE eval_department (dept_id IN employees.department_id%TYPE) AS CURSOR emp_cursor IS SELECT * FROM EMPLOYEES WHERE DEPARTMENT_ID = eval_department.dept_id; emp_record EMPLOYEES%ROWTYPE; -- for row returned by cursor all_evals BOOLEAN; -- true if all employees in dept need evaluations today DATE; BEGIN today := SYSDATE; IF (EXTRACT(MONTH FROM today) < 6) THEN all_evals := FALSE; -- only new employees need evaluations ELSE all_evals := TRUE; -- all employees need evaluations END IF; OPEN emp_cursor; DBMS_OUTPUT.PUT_LINE ( 'Determining evaluations necessary in department # ' || dept_id ); LOOP FETCH emp_cursor INTO emp_record; EXIT WHEN emp_cursor%NOTFOUND; IF all_evals THEN add_eval(emp_record.employee_id, today); ELSIF (eval_frequency(emp_record.employee_id) = 2) THEN add_eval(emp_record.employee_id, today); END IF; END LOOP; DBMS_OUTPUT.PUT_LINE('Processed ' || emp_cursor%ROWCOUNT || ' records.'); CLOSE emp_cursor; END eval_department;(Pour obtenir un exemple étape par étape de la modification du corps d'un package, reportez-vous à la section "Tutorial : Declaring Variables and Constants in a Subprogram".)
-
Compilez la spécification de package EMP_EVAL.
-
Compilez le corps de package EMP_EVAL.
A propos des variables de curseur
Une variable de curseur est semblable à un curseur, mais elle n'est pas limitée à une seule requête. Vous pouvez ouvrir une variable de curseur pour une requête, traiter l'ensemble de résultats, puis utiliser la variable de curseur pour une autre requête. Les variables de curseur permettent la transmission de résultats de requête entre les sous-programmes.
Pour plus d'informations sur les curseurs, reportez-vous à la section "A propos des curseurs".
Pour déclarer une variable de curseur, déclarez un type REF CURSOR, puis déclarez une variable de ce type (par conséquent, les variable de curseur est souvent appelées REF CURSOR). Un type REF CURSOR peut être fort ou faible.
Le type de renvoi REF CURSOR indique un type de renvoi, qui correspond au type ENREGISTREMENT de ses variables du curseur. Le compilateur PL/SQL ne permet pas l'utilisation de ces variables du curseur de type Fort pour les requêtes qui renvoient les lignes qui ne correspondent pas au type de renvoi. Les types REF CURSOR forts engendrent moins d'erreurs que le type faible, mais les type faibles sont plus flexibles.
La forme de faible du type REF CURSOR n'indique aucun type de renvoi. Le compilateur PL/SQL accepte les variables de curseur de type faible dans toutes les requêtes. Les types REF CURSOR faibles sont interchangeables. Ainsi, au lieu de créer des types REF CURSOR faibles, vous pouvez utiliser le type de curseur faible prédéfini SYS_REFCURSOR.
Après avoir déclaré une variable de curseur, vous devez l'ouvrir pour une requête spécifique (à l'aide de l'instruction OPEN FOR), extraire les lignes de l'ensemble des résultats une par un (à l'aide de l'instruction FETCH), puis fermer le curseur (à l'aide de l'instruction CLOSE) ou l'ouvrir pour une autre requête spécifique (à l'aide de l'instruction OPEN FOR). L'ouverture de la variable de curseur pour une autre requête la ferme pour la requête précédente. Suite à la fermeture du curseur pour une requête spécifique, vous ne pouvez plus extraire les enregistrements de l'ensemble de résultats de cette requête, ni visualiser les valeurs des attributs du curseur.
Voir aussi :
-
Manuel Oracle Database PL/SQL Language Reference, pour plus d'informations sur l'utilisation des variables du curseur
-
Manuel Oracle Database PL/SQL Language Reference pour la syntaxe de la déclaration de variables de curseur
Utilisation d'une variable de curseur pour extraire les lignes de l'ensemble de résultats, une à la fois
Vous pouvez utiliser une variable de curseur pour extraire les lignes de l'ensemble de résultats une par une.
La procédure suivante utilise chaque instruction nécessaire dans sa forme la plus simple, mais fournit les références correspondantes à la syntaxe complète.
Procédure d'utilisation d'une variable de curseur pour extraire les lignes d'un ensemble de résultats une par une :
-
Dans la partie de déclaration, effectuez les opérations suivantes :
-
Déclarez le type REF CURSOR :
TYPE cursor_type IS REF CURSOR [ RETURN return_type ];Pour connaître le syntaxe complète des déclaration de type REF CURSOR, reportez-vous au manuelOracle Database PL/SQL Language Reference.
-
Déclarez une variable de curseur de ce type :
cursor_variable cursor_type;Pour connaître la syntaxe complète des déclarations de variable de curseur, reportez-vous au guide Oracle Database PL/SQL Language Reference.
-
Déclarez un enregistrement pouvant contenir la ligne renvoyée par le curseur :
record_name return_type;Pour obtenir des informations complètes sur la syntaxe des déclaration d'enregistrements, reportez-vous au guide Oracle Database PL/SQL Language Reference.
-
-
Dans la partie d'exécution, effectuez les opérations suivantes :
-
Ouvrez la variable de curseur pour une requête spécifique :
OPEN cursor_variable FOR query;Pour plus d'informations sur la syntaxe de l'instruction OPEN FOR, reportez-vous au guide Oracle Database PL/SQL Language Reference.
-
Extrayez, une par une, les lignes de la variable du curseur (lignes de l'ensemble de résultats) à l'aide d'une instruction LOOP dont le syntaxe ressemble à l'exemple suivant :
LOOP FETCH cursor_variable INTO record_name; EXIT WHEN cursor_variable%NOTFOUND; -- Process row that is in record_name: statement; [ statement; ]... END LOOP;Pour plus d'informations sur la syntaxe de l'instruction FETCH, reportez-vous au guide Oracle Database PL/SQL Language Reference.
-
Fermez la variable de curseur :
CLOSE cursor_variable;Vous pouvez également ouvrir la variable de curseur pour une autre requête, ce qui la ferme pour la requête en cours.
Pour plus d'informations sur la syntaxe de l'instruction CLOSE, reportez-vous au guide Oracle Database PL/SQL Language Reference.
-
Tutoriel : Utilisation d'une variable de curseur pour extraire les lignes de l'ensemble de résultats, une à la fois
Les étapes suivantes montrent comment modifier la procédure EMP_EVAL.EVAL_DEPARTMENT afin qu'elle utilise une variable de curseur au lieu d'un curseur déclaré (qui lui permet de traiter plusieurs services) et comment rendre EMP_EVAL.EVAL_DEPARTMENT et EMP_EVAL.ADD_EVAL plus efficaces.
Ce tutoriel présente également l'optimisation des procédures EMP_EVAL.EVAL_DEPARTMENT et EMP_EVAL.ADD_EVAL : au lieu de transmettre un champ d'un enregistrement à ADD_EVAL et que ADD_EVAL utilise trois autres champs du même enregistrement afin d'extraire trois autres champs, EVAL_DEPARTMENT transmet l'enregistrement entier à ADD_EVAL et ADD_EVAL utilise la notation par points pour accéder aux valeurs des trois autres champs.
Pour modifier la procédure EMP_EVAL.EVAL_DEPARTMENT afin d'utiliser une variable du curseur, procédez Comme suit :
-
Dans la spécification de package EMP_EVAL, ajoutez la déclaration et la définition de type REF CURSOR comme indiqué en caractères gras dans l'exemple suivant :
CREATE OR REPLACE PACKAGE emp_eval AS PROCEDURE eval_department (dept_id IN employees.department_id%TYPE); PROCEDURE eval_everyone; FUNCTION calculate_score(eval_id IN scores.evaluation_id%TYPE , perf_id IN scores.performance_id%TYPE) RETURN NUMBER; TYPE SAL_INFO IS RECORD ( j_id jobs.job_id%type , sal_min jobs.min_salary%type , sal_max jobs.max_salary%type , salary employees.salary%type , sal_raise NUMBER(3,3)); TYPE emp_refcursor_type IS REF CURSOR RETURN employees%ROWTYPE; END emp_eval; -
Dans le corps de package EMP_EVAL, ajoutez une déclaration anticipée pour la procédure EVAL_LOOP_CONTROL et modifiez la déclaration de la procédure ADD_EVAL comme indiqué en caractères gras.
CREATE OR REPLACE PACKAGE BODY EMP_EVAL AS FUNCTION eval_frequency (emp_id IN EMPLOYEES.EMPLOYEE_ID%TYPE) RETURN PLS_INTEGER; PROCEDURE salary_schedule(emp IN sal_info); PROCEDURE add_eval(emp_record IN EMPLOYEES%ROWTYPE, today IN DATE); PROCEDURE eval_loop_control(emp_cursor IN emp_refcursor_type); ...(Pour obtenir un exemple étape par étape de la modification du corps d'un package, reportez-vous à la section "Tutorial : Declaring Variables and Constants in a Subprogram".)
-
Modifiez la procédure EVAL_DEPARTMENT pour extraire trois ensembles de résultats distincts en fonction du service et appeler la procédure EVAL_LOOP_CONTROL comme indiqué en caractères gras dans l'exemple suivant :
PROCEDURE eval_department(dept_id IN employees.department_id%TYPE) AS emp_cursor emp_refcursor_type; current_dept departments.department_id%TYPE; BEGIN current_dept := dept_id; FOR loop_c IN 1..3 LOOP OPEN emp_cursor FOR SELECT * FROM employees WHERE current_dept = eval_department.dept_id; DBMS_OUTPUT.PUT_LINE ('Determining necessary evaluations in department #' || current_dept); eval_loop_control(emp_cursor); DBMS_OUTPUT.PUT_LINE ('Processed ' || emp_cursor%ROWCOUNT || ' records.'); CLOSE emp_cursor; current_dept := current_dept + 10; END LOOP; END eval_department; -
Modifiez la procédure ADD_EVAL comme indiqué ci-dessous :
PROCEDURE add_eval(emp_record IN employees%ROWTYPE, today IN DATE) AS -- (Delete local variables) BEGIN INSERT INTO EVALUATIONS ( evaluation_id, employee_id, evaluation_date, job_id, manager_id, department_id, total_score ) VALUES ( evaluations_sequence.NEXTVAL, -- evaluation_id emp_record.employee_id, -- employee_id today, -- evaluation_date emp_record.job_id, -- job_id emp_record.manager_id, -- manager_id emp_record.department_id, -- department_id 0 -- total_score ); END add_eval; -
Avant
END EMP_EVAL, ajoutez la procédure suivante qui extrait les enregistrements individuels de l'ensemble de résultats et les traite :PROCEDURE eval_loop_control (emp_cursor IN emp_refcursor_type) AS emp_record EMPLOYEES%ROWTYPE; all_evals BOOLEAN; today DATE; BEGIN today := SYSDATE; IF (EXTRACT(MONTH FROM today) < 6) THEN all_evals := FALSE; ELSE all_evals := TRUE; END IF; LOOP FETCH emp_cursor INTO emp_record; EXIT WHEN emp_cursor%NOTFOUND; IF all_evals THEN add_eval(emp_record, today); ELSIF (eval_frequency(emp_record.employee_id) = 2) THEN add_eval(emp_record, today); END IF; END LOOP; END eval_loop_control; -
Avant
END EMP_EVAL, ajoutez la procédure suivante qui extrait l'ensemble de résultats contenant l'ensemble des employés de la société :PROCEDURE eval_everyone AS emp_cursor emp_refcursor_type; BEGIN OPEN emp_cursor FOR SELECT * FROM employees; DBMS_OUTPUT.PUT_LINE('Determining number of necessary evaluations.'); eval_loop_control(emp_cursor); DBMS_OUTPUT.PUT_LINE('Processed ' || emp_cursor%ROWCOUNT || ' records.'); CLOSE emp_cursor; END eval_everyone; -
Compilez la spécification de package
EMP_EVAL. -
Compilez le corps de package
EMP_EVAL.