Uso di record e cursori
I componenti script in questa pagina sono utilizzati solo per scopi di navigazione e non alterano in alcun modo il contenuto.
È possibile memorizzare i valori dei dati nei record e utilizzare un cursore come puntatore a un set di risultati e alle informazioni di elaborazione correlate.
Per ulteriori informazioni sui record, vedere anche: Oracle Database PL/SQL Language Reference
Informazioni sui record
Un record è una variabile composta PL/SQL in grado di memorizzare valori di dati di tipi diversi. È possibile considerare i componenti interni (campi) come variabili scalari. È possibile passare interi record come parametri del sottoprogramma. I record sono utili per contenere i dati delle righe delle tabelle o di determinate colonne di righe delle tabelle.
Un record è una variabile composita PL/SQL che può memorizzare valori di dati di diversi tipi, in modo analogo al tipo struct in C, C++ o Java. I componenti interni di un record sono chiamati campi. Per accedere a un campo di un record si utilizza la notazione a punti: record_name.field_name.
È possibile trattare i campi dei record come variabili scalari. È inoltre possibile passare interi record come parametri del sottoprogramma.
I record sono utili per contenere i dati delle righe delle tabelle o di determinate colonne di righe delle tabelle. Ogni campo del record corrisponde a una colonna della tabella.
Per creare un record sono disponibili i tre modi riportati di seguito.
-
Dichiarare un tipo RECORD e quindi dichiarare una variabile di questo tipo.
Utilizzare la sintassi riportata di seguito.
TYPE record_name IS RECORD ( field_name data_type [:= initial_value] [, field_name data_type [:= initial_value ] ]... ); variable_name record_name; -
Dichiarare una variabile di tipo table_name%ROWTYPE.
I campi del record hanno gli stessi nomi e tipi di dati delle colonne della tabella.
-
Dichiarare una variabile di tipo cursor_name%ROWTYPE.
I campi del record hanno gli stessi nomi e tipi di dati delle colonne della tabella nella clausola FROM dell'istruzione SELECT del cursore.
Vedere anche:
-
Oracle Database PL/SQL Language Reference per ulteriori informazioni sulla definizione dei tipi RECORD e la dichiarazione dei RECORD del tipo specificato
-
Oracle Database PL/SQL Language Reference per la sintassi della definizione di un tipo RECORD
-
Oracle Database PL/SQL Language Reference per ulteriori informazioni sull'attributo %ROWTYPE
-
Oracle Database PL/SQL Language Reference per la sintassi dell'attributo %ROWTYPE
Esercitazione: Dichiarazione di un tipo RECORD
I passi riportati di seguito mostrano come utilizzare lo strumento Modifica SQL Developer per dichiarare un tipo RECORD, sal_info, i cui campi possono contenere le informazioni stipendio per un dipendente (ID mansione, stipendio minimo e massimo per l'ID mansione, stipendio corrente e aumento suggerito).
Passi per dichiarare il tipo di RECORD sal_info:
-
Nel frame Connessioni espandere hr_conn.
Sotto l'icona hr_conn viene visualizzata una lista di tipi d'oggetto dello schema.
-
Espandere Package.
Viene visualizzata una lista di package.
-
fare clic con il pulsante destro del mouse su EMP_EVAL.
Viene visualizzata una lista di scelte.
-
Selezionare Modifica.
Viene aperto il riquadro EMP_EVAL, in cui è riportata l'istruzione
CREATE PACKAGEche ha creato il 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; -
Nel riquadro EMP_EVAL, immediatamente prima di
END EMP_EVAL, aggiungere questo codice: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) );Il titolo del riquadro è in corsivo, a significare che le modifiche non sono state salvate nel database.
-
Selezionare l'icona Compila.
La specifica package modificata viene compilata e salvata nel database. Il titolo del riquadro EMP_EVAL non è più in corsivo.
Ora è possibile dichiarare i record di tipo sal_info, come in "Esercitazione: Creazione e richiamo del sottoprogramma con un parametro record".
Esercitazione: Creazione e richiamo di un sottoprogramma con un parametro record
I passi riportati di seguito mostrano come utilizzare lo strumento Modifica di SQL Developer per creare e richiamare un sottoprogramma con un parametro del tipo di record sal_info.
Il tipo di RECORD sal_info è stato creato in "Esercitazione: dichiarazione di un tipo di RECORD".
Questa esercitazione mostra come utilizzare lo strumento Modifica di SQL Developer per completare i task riportati di seguito.
-
Creare una procedura, SALARY_SCHEDULE, con un parametro di tipo
sal_info. -
Modificare la funzione EVAL_FREQUENCY in modo che dichiari un record, emp_sal, di tipo
sal_info, popoli i relativi campi e lo passi alla procedura SALARY_SCHEDULE.
Poiché EVAL_FREQUENCY richiama SALARY_SCHEDULE, la dichiarazione di SALARY_SCHEDULE deve precedere la dichiarazione di EVAL_FREQUENCY (altrimenti il package non viene compilato). Tuttavia, la definizione di SALARY_SCHEDULE può trovarsi in qualsiasi punto del package body.
Passi per creare SALARY_SCHEDULE e modificare EVAL_FREQUENCY:
-
Nel frame Connessioni espandere hr_conn.
-
Nella lista dei tipi di oggetto schema espandere Pacchetti.
-
Nell'elenco dei pacchetti espandere EMP_EVAL.
-
Nell'elenco delle opzioni, fare clic con il pulsante destro del mouse su Corpo EMP_EVAL.
-
Nell'elenco di scelte, selezionare Modifica.
Viene visualizzato un riquadro Corpo EMP_EVAL, in cui è mostrato il codice per il package body.
-
Nel riquadro Corpo EMP_EVAL, immediatamente prima di
END EMP_EVAL, aggiungere una definizione della procedura 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;Il titolo del riquadro è in corsivo, a significare che le modifiche non sono state salvate nel database.
-
Nel riquadro Corpo EMP_EVAL, immettere la funzione eval_frequency e le procedure stipendio_schedule e add_eval nella seguente posizione:
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 -
Modificare la funzione
EVAL_FREQUENCYapportando le modifiche riportate di seguito.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; -
Selezionare Compila.
Informazioni sui cursori
Quando viene eseguita un'istruzione SQL, Oracle Database memorizza il set di risultati e i dati di elaborazione in un'area SQL privata senza nome. Un puntatore a tale area senza nome, denominato cursore, consente di recuperare il set di risultati una riga alla volta. Gli attributi del cursore restituiscono le informazioni sullo stato del cursore.
Ogni volta che si esegue un'istruzione DML SQL o un'istruzione SELECT INTO PL/SQL, PL/SQL apre un cursore implicito. È possibile ottenere informazioni su questo cursore dai relativi attributi, ma non è possibile controllarli. In seguito all'esecuzione dell'istruzione, il database chiude il cursore; tuttavia, i valori degli attributi restano disponibili fino a quando non viene eseguita un'altra istruzione DML o SELECT INTO.
PL/SQL consente anche di dichiarare cursori. Un cursore dichiarato ha un nome ed è associato a una Query (istruzione SQL SELECT), solitamente una Query che restituisce più righe. Dopo aver dichiarato un cursore, è necessario elaborarlo, implicitamente o esplicitamente. Per elaborare il cursore in modo implicito, utilizzare un cursore FOR LOOP. La sintassi è:
FOR record_name IN cursor_name LOOP
statement
[ statement ]...
END LOOP;
Per elaborare il cursore in modo esplicito, aprirlo (con l'istruzione OPEN), recuperare le righe dal set di risultati uno alla volta o in blocco (con l'istruzione FETCH) e chiudere il cursore (con l'istruzione CLOSE). Dopo aver chiuso il cursore, non è possibile recuperare i record dal set di risultati né vedere i valori degli attributi del cursore.
La sintassi per il valore di un attributo del cursore implicito è SQL%attribute (ad esempio, SQL%FOUND). SQL%attribute fa sempre riferimento all'ultima istruzione DML o SELECT INTO eseguita.
La sintassi per il valore dell'attributo di cursore dichiarato è cursor_name%attribute (ad esempio, c1%FOUND). La tabella 1 elenca gli attributi e i valori che possono restituire il cursore. (i cursori impliciti hanno attributi aggiuntivi che non vengono descritti in questo manuale).
Tabella 1 - Valori attributo cursore
| Attributo | Valori per cursore dichiarato | Valori per il cursore implicito |
|---|---|---|
| % TROVATO | Se il cursore è aperto (nota a piè di pagina 1) ma non si è tentata alcuna operazione di fetch, NULL. Se l'operazione di FETCH più recente ha restituito una riga, TRUE. Se l'operazione di fetch più recente non ha restituito una riga, FALSE. |
Se non è stata eseguita alcuna istruzione DML o SELECT INTO, NULL. Se l'istruzione DML o SELECT INTO più recente ha restituito una riga, TRUE. Se l'istruzione DML o SELECT INTO più recente non ha restituito una riga, FALSE. |
| %NON TROVATO | Se il cursore è aperto (nota a piè di pagina 1) ma non si è tentata alcuna operazione di fetch, NULL. Se l'operazione di FETCH più recente ha restituito una riga, FALSE. Se l'operazione di fetch più recente non ha restituito una riga, TRUE. |
Se non è stata eseguita alcuna istruzione DML o SELECT INTO, NULL. Se l'istruzione DML o SELECT INTO più recente ha restituito una riga, Se l'istruzione DML o SELECT INTO più recente non ha restituito una riga, |
| % CONTEGGIO RIGHE | Se il cursore è aperto (nota a piè di pagina 1), un numero maggiore o uguale a zero. | NULL se non è stata eseguita alcuna istruzione DML o SELECT INTO; altrimenti, un numero superiore o uguale a zero. |
| %SOPEN | Se il cursore è aperto, TRUE; in caso contrario, FALSE. | Sempre FALSO. |
Nota a piè di pagina 1: se il cursore non è aperto, l'attributo genera l'eccezione predefinita INVALID_CURSOR.
Vedere anche:
-
"Informazioni sulle istruzioni DML (Data Manipulation Language)"
-
Oracle Database PL/SQL Language Reference per ulteriori informazioni sull'istruzione SELECT INTO
-
Oracle Database PL/SQL Language Reference per ulteriori informazioni sulla gestione dei cursori in PL/SQL
Utilizzo di un cursore dichiarato per recuperare le righe del set di risultati una alla volta
È possibile utilizzare un cursore dichiarato per recuperare le righe del set di risultati una alla volta.
La procedura seguente utilizza ogni istruzione necessaria nella forma più semplice, ma fornisce i riferimenti alla sintassi completa.
Passi per utilizzare un cursore dichiarato per recuperare le righe del set di risultati una alla volta:
-
Nella parte dichiarativa:
-
Dichiarare il cursore:
CURSOR cursor_name IS query;Per la sintassi completa di dichiarazione di cursore dichiarata, vedere Oracle Database PL/SQL Language Reference.
-
Dichiarare un record per contenere la riga restituita dal cursore.
record_name cursor_name%ROWTYPE;Per completare la sintassi %ROWTYPE, vedere Oracle Database PL/SQL Language Reference.
-
-
Nella parte eseguibile:
-
Aprire il cursore:
OPEN cursor_name;Per la sintassi completa dell'istruzione OPEN, vedere Oracle Database PL/SQL Language Reference.
-
Recupera le righe dal cursore (righe del set di risultati) una alla volta utilizzando un'istruzione LOOP con una sintassi simile al seguente:
LOOP FETCH cursor_name INTO record_name; EXIT WHEN cursor_name%NOTFOUND; -- Process row that is in record_name: statement; [ statement; ]... END LOOP;Per la sintassi completa dell'istruzione FETCH, vedere Oracle Database PL/SQL Language Reference.
-
Chiudere il cursore:
CLOSE cursor_name;
-
Per la sintassi completa dell'istruzione CLOSE, vedere Oracle Database PL/SQL Language Reference.
Esercitazione: Utilizzo di un cursore dichiarato per recuperare le righe del set di risultati una alla volta
I passaggi seguenti mostrano come implementare la procedura EMP_EVAL.EVAL_DEPARTMENT, che utilizza un cursore dichiarato, emp_cursor.
Per implementare la procedura EMP_EVAL.EVAL_DEPARTMENT, procedere come segue.
-
Nella specifica package EMP_EVAL modificare la dichiarazione della procedura EVAL_DEPARTMENT come mostrato in basso:
PROCEDURE eval_department(dept_id IN employees.department_id%TYPE); -
Nel package body EMP_EVAL modificare la definizione della procedura EVAL_DEPARTMENT come mostrato in grassetto.
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;Per un esempio dettagliato di modifica di un package body, vedere "Esercitazione: Dichiarazione di variabili e costanti in un sottoprogramma".
-
Compilare la specifica package EMP_EVAL.
-
Compilare il package body EMP_EVAL.
Informazioni sulle variabili del cursore
Una variabile del cursore è simile a un cursore, ad eccezione del fatto che non è limitata a una query. È possibile aprire una variabile cursore per una query, elaborare il set di risultati e quindi utilizzare la variabile cursore per un'altra query. Le variabili cursore sono utili per passare il risultato delle query tra due sottoprogrammi.
Per informazioni sui cursori, vedere "Informazioni sui cursori".
Per dichiarare una variabile del cursore, è necessario dichiarare un tipo REF CURSOR e quindi dichiarare una variabile del tipo specificato (pertanto, una variabile del cursore viene spesso chiamata REF CURSOR). Un tipo REF CURSOR può essere forte o debole.
Un tipo REF CURSOR forte specifica un tipo restituito , che rappresenta il tipo RECORD delle relative variabili del cursore. Il compilatore PL/SQL non consente di utilizzare queste variabili del cursore forti per le query che restituiscono righe diverse dal tipo restituito. I tipi REF CURSOR forti sono meno inclini agli errori rispetto ai modelli deboli, ma questi ultimi sono più flessibili.
Un tipo REF CURSOR debole non specifica un tipo restituito. Il compilatore PL/SQL accetta variabili del cursore deboli in qualsiasi query. I tipi CURSOR REF deboli sono intercambiabili; pertanto, invece di creare tipi REF CURSOR deboli, è possibile utilizzare il tipo di cursore debole tipo predefinito SYS_REFCURSOR.
Dopo aver dichiarato una variabile cursore, è necessario aprirla per una query specifica (con l'istruzione OPEN FOR), recuperare le righe una alla volta dal set di risultati (con l'istruzione FETCH) e quindi chiudere il cursore (con l'istruzione CLOSE) o aprirlo per un'altra query specifica (con l'istruzione OPEN FOR). L'apertura della variabile cursore per un'altra query ne determina la chiusura per la query precedente. Dopo aver chiuso una variabile cursore per una query specifica, non è possibile recuperare i record dal set di risultati della query né vedere i valori degli attributi del cursore per la query.
Vedere anche:
-
Oracle Database PL/SQL Language Reference per ulteriori informazioni sull'uso delle variabili del cursore
-
Oracle Database PL/SQL Language Reference per la sintassi della dichiarazione di variabile cursore
Uso di una variabile del cursore per recuperare le righe del set di risultati una alla volta
Per recuperare le righe del set di risultati una alla volta, è possibile utilizzare una variabile cursore.
La procedura riportata di seguito utilizza ogni istruzione necessaria nella forma più semplice, ma fornisce i riferimenti alla sintassi completa.
Passi per utilizzare una variabile cursore per recuperare le righe del set di risultati una alla volta:
-
Nella parte dichiarativa:
-
Dichiarare il tipo REF CURSOR:
TYPE cursor_type IS REF CURSOR [ RETURN return_type ];Per la sintassi completa della dichiarazione di tipo REF CURSOR, vedere Oracle Database PL/SQL Language Reference.
-
Dichiarare una variabile di cursore del tipo specificato:
cursor_variable cursor_type;Per la sintassi completa della dichiarazione delle variabili del cursore, vedere Oracle Database PL/SQL Language Reference.
-
Dichiarare un record per contenere la riga restituita dal cursore.
record_name return_type;Per informazioni complete sulla sintassi delle dichiarazioni del record, vedere Oracle Database PL/SQL Language Reference.
-
-
Nella parte eseguibile:
-
Aprire la variabile del cursore per una query specifica:
OPEN cursor_variable FOR query;Per informazioni complete sulla sintassi dell'istruzione OPEN FOR, vedere Oracle Database PL/SQL Language Reference.
-
Recupera le righe dalla variabile del cursore (righe del set di risultati) una alla volta, utilizzando un'istruzione LOOP che ha una sintassi simile alla seguente:
LOOP FETCH cursor_variable INTO record_name; EXIT WHEN cursor_variable%NOTFOUND; -- Process row that is in record_name: statement; [ statement; ]... END LOOP;Per informazioni complete sulla sintassi dell'istruzione FETCH, vedere Oracle Database PL/SQL Language Reference.
-
Chiudere la variabile del cursore:
CLOSE cursor_variable;In alternativa, è possibile aprire la variabile del cursore per un'altra query, determinandone così la chiusura per la query corrente.
Per informazioni complete sulla sintassi dell'istruzione CLOSE, vedere Oracle Database PL/SQL Language Reference.
-
Esercitazione: Uso di una variabile del cursore per recuperare le righe del set di risultati una alla volta
Questa procedura mostra come modificare la procedura EMP_EVAL.EVAL_DEPARTMENT in modo che utilizzi una variabile del cursore anziché un cursore dichiarato (che gli consente di elaborare più reparti) e come rendere più efficienti EMP_EVAL.EVAL_DEPARTMENT e EMP_EVAL.ADD_EVAL.
Questa esercitazione dimostra come rendere più efficiente EMP_EVAL.EVAL_DEPARTMENT e EMP_EVAL.ADD_EVAL: invece di passare il campo di un record a ADD_EVAL e fare in modo che ADD_EVAL utilizzi tre query per estrarre altri tre campi dello stesso record, EVAL_DEPARTMENT passa l'intero record a ADD_EVAL e ADD_EVAL utilizza la notazione a punti per accedere ai valori degli altri tre campi.
Passi per modificare la procedura EMP_EVAL.EVAL_DEPARTMENT in modo che utilizzi una variabile di cursore:
-
Nella specifica package EMP_EVAL aggiungere la dichiarazione della procedura e la definizione del tipo REF CURSOR, come mostrato nell'esempio riportato di seguito.
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; -
Nel package body EMP_EVAL aggiungere una dichiarazione di inoltro per la procedura EVAL_LOOP_CONTROL e modificare la dichiarazione della procedura ADD_EVAL, come mostrato in basso:
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); ...Per un esempio dettagliato di modifica di un package body, vedere "Esercitazione: Dichiarazione di variabili e costanti in un sottoprogramma".
-
Modificare la procedura EVAL_DEPARTMENT per recuperare tre set di risultati separati, in base al dipartimento, e per richiamare il processo EVAL_LOOP_CONTROL, come mostrato nell'esempio riportato di seguito.
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; -
Modificare la procedura ADD_EVAL come indicato di seguito.
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; -
Prima del
END EMP_EVAL, aggiungere la seguente procedura, che recupera i singoli record dal set di risultati e li elabora: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; -
Prima del
END EMP_EVALaggiungere la seguente procedura, che recupera un set di risultati contenente tutti i dipendenti nella società: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; -
Compilare la specifica package
EMP_EVAL. -
Compilare il package body
EMP_EVAL.