Uso de Registros y Cursores
El contenido del script de esta página es sólo para fines de navegación y no modifica el contenido de ninguna forma.
Puede almacenar valores de datos en registros y utilizar un cursor como puntero para un juego de resultados y la información de procesamiento relacionada.
Consulte también: Referencia de lenguaje PL/SQL de Oracle Database para obtener más información sobre los registros
Acerca de los Registros
Un registro es una variable compuesta PL/SQL que puede almacenar valores de datos de diferentes tipos. Puede tratar los componentes internos (campos) como variables escalares. Puede transferir registros completos como parámetros de subprograma. Los registros son útiles para contener datos de las filas de tablas o de determinadas columnas de las filas de tablas.
Un registro es una variable compuesta PL/SQL que puede almacenar valores de datos de diferentes tipos, similares a un tipo de estructura en C, C++ o Java. Los componentes internos de un registro se llaman campos. Para acceder a un campo de registro, utilice notación de punto: nombre_campo_registro.
Puede tratar campos de registro como variables escalares. También puede transferir registros completos como parámetros de subprograma.
Los registros son útiles para contener datos de las filas de tablas o de determinadas columnas de las filas de tablas. Cada campo de registro corresponde a una columna de tabla.
Hay tres formas de crear un registro:
-
Declare un tipo RECORD y, después, declare una variable de ese tipo.
Utilice la siguiente sintaxis:
TYPE record_name IS RECORD ( field_name data_type [:= initial_value] [, field_name data_type [:= initial_value ] ]... ); variable_name record_name; -
Declarar una variable del tipo table_name%ROWTYPE.
Los campos del registro tienen los mismos nombres y tipos de datos que las columnas de la tabla.
-
Declare una variable del tipo cursor_name%ROWTYPE.
Los campos del registro tienen los mismos nombres y tipos a los que las columnas de la tabla en la cláusula FROM de la sentencia SELECT del cursor.
Consulte además:
-
Referencia de lenguaje PL/SQL de Oracle Database para obtener más información sobre la definición de tipos RECORD y la declaración de registros de ese tipo
-
Referencia de lenguaje PL/SQL de Oracle Database para la sintaxis de una definición de tipo RECORD
-
Para obtener más información sobre el atributo %ROWTYPE, consulte Oracle Database PL/SQL Language Reference
-
Oracle Database PL/SQL Language Reference para obtener más información sobre la sintaxis del atributo %ROWTYPE
Tutorial: Declaración de un Tipo RECORD
En los siguientes pasos se muestra cómo utilizar la herramienta Editar SQL Developer para declarar un tipo RECORD, sal_info, cuyos campos pueden contener los datos del salario de un empleado: el identificador de Trabajo, el sueldo mínimo y máximo para ese identificador de Trabajo, el sueldo actual y el aumento sugerido.
Pasos para declarar el tipo RECORD sal_info:
-
En el marco Conexiones, expanda hr_conn.
Bajo el icono hr_conn, aparecerá una lista de tipos del objeto de esquema.
-
Amplíe Paquetes.
Aparecerá una lista de paquetes.
-
Haga clic con el mouse en EMP_EVAL.
Aparecerá una lista de opciones.
-
Seleccione Editar.
Se mostrará el panel EMP_EVAL en el que se ha creado el paquete:
CREATE PACKAGECREATE 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; -
En el panel EMP_EVAL, inmediatamente antes de
END EMP_EVAL, agregue este código: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) );El título del panel aparece en cursiva, lo que indica que los cambios no se han guardado para la base de datos.
-
Seleccione el icono Compilar.
La especificación del paquete cambiada se compila y guarda en la base de datos. El título del panel EMP_EVAL dejará de estar en cursiva.
Ahora puede declarar registros del tipo sal_info, como se indica en "Tutorial: Creación e Invocación del Subprograma con un Parámetro de Registro".
Tutorial: Creación e Invocación de un Subprograma con un Parámetro de Registro
Los siguientes pasos muestran cómo utilizar la herramienta de edición de SQL Developer para crear y llamar a un subprograma con un parámetro del tipo de registro sal_info.
El tipo de registro sal_info se ha creado en "Tutorial: Declaración de un tipo de registro".
En este tutorial se muestra cómo utilizar la herramienta de edición de SQL Developer para realizar las siguientes tareas:
-
Crear un procedimiento, SALARY_SCHEDULE, que tiene un parámetro del tipo
sal_info. -
Cambiar la función EVAL_FREQUENCY de forma que declare un registro, emp_sal, del tipo
sal_info, rellene sus campos y el pase al procedimiento SALARY_SCHEDULE.
Puesto que EVAL_FREQUENCY invocará SALARY_SCHEDULE, la declaración de SALARY_SCHEDULE debe preceder a la declaración de EVAL_FREQUENCY (de lo contrario, el paquete no se compilará). Sin embargo, la definición de SALARY_SCHEDULE puede estar en cualquier lugar del cuerpo del paquete.
Pasos para crear SALARY_SCHEDULE y cambiar EVAL_FREQUENCY:
-
En el marco Conexiones, expanda hr_conn.
-
En la lista de tipos de objetos de esquema, amplíe Paquetes.
-
En la lista de paquetes, expanda EMP_EVAL.
-
En la lista de opciones, haga clic con el botón derecho en EMP_EVAL Body (Cuerpo EVAL).
-
En la lista de opciones, seleccione Editar.
Aparecerá el panel del cuerpo de EMP_EVAL, en el que se muestra el código del cuerpo del paquete.
-
En el panel del cuerpo de EMP_EVAL, inmediatamente antes de la
END EMP_EVAL, agregue la siguiente definición del procedimiento 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;El título del panel aparece en cursiva, lo que indica que los cambios no se han guardado para la base de datos.
-
En el panel Cuerpo EMP_EVAL, escriba la función eval_frequency y los procedimientos salary_schedule y add_eval en la siguiente posición:
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 -
Edite la función
EVAL_FREQUENCY, realizando los siguientes cambios: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; -
Seleccione Compilar.
Acerca de los Cursores
Cuando Oracle Database ejecuta una sentencia SQL, almacena la información de procesamiento y el juego de resultado en un área SQL privada sin nombre. Un puntero a esta área sin nombre, llamado cursor, le permite recuperar el juego de resultado de una fila a una. Los atributos del cursor devuelven información sobre el estado del cursor.
Cada vez que ejecuta una sentencia DML SQL o una sentencia SELECT INTO PL/SQL, PL/SQL abre un cursor implícito. Puede obtener información sobre este cursor de sus atributos, pero no puede controlarlo. Después de ejecutar la sentencia, la base de datos cierra el cursor; sin embargo, sus valores del atributo permanecen disponibles hasta la ejecución de otra sentencia DML o SELECT INTO.
PL/SQL también permite declarar los cursores. Un cursor explícito tiene un nombre y se asocia a una consulta (sentencia SQL SELECT), generalmente, a una que devuelve varias filas. Después de declarar un cursor, debe procesarlo, ya sea implícita o explícitamente. Para procesar el cursor de forma implícita, utilice un cursor FOR LOOP. La sintaxis es:
FOR record_name IN cursor_name LOOP
statement
[ statement ]...
END LOOP;
Para procesar el cursor de forma explícita, ábralo (con la sentencia OPEN), recupere las filas del juego de resultados de una en una o en bloque (con la sentencia FETCH) y cierre el cursor (con la sentencia CLOSE). Después de cerrar el cursor, no puede recuperar los registros del juego de resultados ni ver los valores de atributo del cursor.
La sintaxis para el valor de un atributo de cursor implícito es SQL%attribute (por ejemplo, SQL%FOUND). SQL%attribute siempre hace referencia a la sentencia DML o SELECT INTO ejecutada más recientemente.
La sintaxis para el valor de un atributo de cursor declarado es cursor_name%attribute (por ejemplo, c1%FOUND). En la Tabla 1 se muestran los atributos de cursor y los valores que pueden devolver. (Los cursores implícitos tienen atributos adicionales que no se tratan en este libro.)
Tabla 1 Valores de atributo de cursor
| Atributo | Valores para el cursor declarado | Valores para el Cursor Implícito |
|---|---|---|
| % ENCONTRADO | Si el cursor está abierto (nota de pie de página 1) pero no se ha intentado realizar ninguna recuperación, NULL. Si la Recuperación más reciente ha devuelto una fila, TRUE. Si la Recuperación más reciente no ha devuelto una fila, FALSE. |
Si no se ha ejecutado ninguna sentencia DML o SELECT INTO, NULL. Si la sentencia DML o SELECT INTO más reciente ha devuelto una fila, TRUE. Si la sentencia DML o SELECT INTO más reciente no ha devuelto una fila, FALSE. |
| %NO ENCONTRADO | Si el cursor está abierto (nota de pie de página 1) pero no se ha intentado realizar ninguna recuperación, NULL. Si la Recuperación más reciente ha devuelto una fila, FALSE. Si la Recuperación más reciente no ha devuelto una fila, TRUE. |
Si no se ha ejecutado ninguna sentencia DML o SELECT INTO, NULL. Si la sentencia DML o SELECT INTO más reciente ha devuelto una fila, Si la sentencia DML o SELECT INTO más reciente no ha devuelto una fila, |
| % DE RECUENTO DE FILAS | Si el cursor está abierto (nota al pie 1), un número mayor o igual a cero. | NULL si no se ha ejecutado ninguna sentencia DML ni SELECT INTO; de lo contrario, un número mayor o igual a cero. |
| %ISABIERTO | Si el cursor está abierto, TRUE; si no, FALSE. | Siempre FALSO. |
Nota al pie 1: si el cursor no está abierto, el atributo emite la excepción predefinida INVALID_CURSOR.
Consulte además:
-
"Acerca de las sentencias de lenguaje de manipulación de datos (DML)"
-
Para obtener más información sobre la sentencia SELECT INTO, consulte Oracle Database PL/SQL Language Reference
-
Referencia de lenguaje PL/SQL de Oracle Database para obtener más información sobre la gestión de cursores en PL/SQL
Uso de un Cursor Declarado para Recuperar Filas de Juego de Resultados de una en una
Puede utilizar un cursor declarado para recuperar las filas del juego de resultados de una en una.
El siguiente procedimiento utiliza cada sentencia necesaria en su forma más sencilla, pero proporciona referencias a su sintaxis completa.
Pasos para utilizar un cursor declarado para recuperar filas de juegos de resultados de una en una:
-
En la parte declarativa:
-
Declare el cursor:
CURSOR cursor_name IS query;Para obtener una sintaxis de declaración de cursor declarada completa, consulte Referencia de lenguaje PL/SQL de Oracle Database.
-
Declare un registro que va a contener la fila devuelta por el cursor:
record_name cursor_name%ROWTYPE;Para obtener una sintaxis %ROWTYPE completa, consulte Referencia de lenguaje PL/SQL de Oracle Database.
-
-
En la parte ejecutable:
-
Abra el cursor:
OPEN cursor_name;Para obtener una sintaxis de sentencia OPEN completa, consulte Referencia de lenguaje PL/SQL de Oracle Database.
-
Recupere una a las filas del cursor (filas del juego de resultados) de una en una, con una sentencia LOOP cuya sintaxis sea similar al siguiente código:
LOOP FETCH cursor_name INTO record_name; EXIT WHEN cursor_name%NOTFOUND; -- Process row that is in record_name: statement; [ statement; ]... END LOOP;Para obtener una sintaxis de sentencia FETCH completa, consulte Referencia de lenguaje PL/SQL de Oracle Database.
-
Cierre el cursor:
CLOSE cursor_name;
-
Para obtener una sintaxis completa de la sentencia CLOSE, consulte Referencia de lenguaje PL/SQL de Oracle Database.
Tutorial: Uso de Un Cursor Declarado para Recuperar Filas de Juego de Resultados de una en una
Los siguientes pasos muestran cómo implementar el procedimiento EMP_EVAL.EVAL_DEPARTMENT, que utiliza un cursor declarado, emp_cursor.
Pasos para implementar el procedimiento EMP_EVAL.EVAL_DEPARTMENT:
-
En la especificación de paquete EMP_EVAL, cambie la declaración del procedimiento EVAL_DEPARTMENT, de la forma que se muestra en negrita
PROCEDURE eval_department(dept_id IN employees.department_id%TYPE); -
En el cuerpo el paquete EMP_EVAL, cambie la definición del procedimiento EVAL_DEPARTMENT, de la forma que se muestra en el siguiente ejemplo:
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;(Para ver un ejemplo detallado de cambio en un cuerpo del paquete, consulte "Tutorial: Declaración de Variables y Constantes en un Subprograma".)
-
Compile la especificación de paquete EMP_EVAL.
-
Compile el cuerpo de paquete EMP_EVAL.
Acerca de las Variables del Cursor
Una variable de cursor es como un cursor que no se limita a una consulta. Puede abrir una variable de cursor para una consulta, procesar el juego de resultados y, después, utilizar la variable de cursor para otra consulta. Las variables de cursor son útiles para transferir resultados de consulta a otro subprograma.
Para obtener información sobre los cursores, consulte "About Cursors".
Para declarar una variable del CURSOR, declare un tipo REF CURSOR y, después, declare una variable del tipo (por eso, una variable del CURSOR se suele llamar REF CURSOR). Un tipo REF CURSOR puede ser fuerte o débil.
Un tipo fuerte REF CURSOR especifica un tipo de devolución, que es el tipo RECORD de sus variables del CURSOR. El compilador PL/SQL no le permite utilizar estas variables tipo fuerte de cursor para consultas que devuelven filas que no sean de tipo de retorno. Los tipos REF CURSOR fuertes son menos propensos a errores que los débiles, pero los débiles son más flexibles.
Un tipo débil REF CURSOR type no especifica un tipo de retorno. El compilador PL/SQL acepta variables de cursor tipo débil en cualquier consulta. Los tipos REF CURSOR débiles son intercambiables; por lo tanto, en lugar de crear tipos REF CURSOR débiles, puede utilizar el tipo del CURSOR débil predefinido SYS_REFCURSOR.
Después de declarar una variable del cursor, debe abrirla para una consulta concreta (con la sentencia OPEN FOR) y, a continuación, cerrar el cursor (con la sentencia CLOSE) o abrirlo para otra consulta concreta (con la sentencia OPEN FOR). Al abrir la variable de cursor para otra consulta, ésta se cierra para la consulta anterior. Después de cerrar una variable de cursor para una consulta concreta, no puede recuperar los registros del juego de resultados de esa consulta, ni ver los valores de atributo del cursor para esa consulta.
Consulte además:
-
Referencia de lenguaje PL/SQL de Oracle Database para obtener más información sobre el uso de variables de cursor
-
Referencia de lenguaje PL/SQL de Oracle Database para la sintaxis de la declaración de variable de cursor
Uso de una Variable de Cursor para Recuperar Filas de Juegos de Resultados una a una
Puede utilizar una variable de cursor para recuperar las filas de juegos de resultados de una en una.
El siguiente procedimiento utiliza cada una de las sentencias necesarias en su forma más sencilla, pero proporciona referencias a su sintaxis completa.
Pasos para utilizar una variable de cursor para recuperar filas de juegos de resultados de una en una:
-
En la parte declarativa:
-
Declare el tipo REF CURSOR:
TYPE cursor_type IS REF CURSOR [ RETURN return_type ];Para obtener una sintaxis de declaración de tipo REF CURSOR completa, consulte Referencia de lenguaje PL/SQL de Oracle Database.
-
Declare una variable del cursor de ese tipo:
cursor_variable cursor_type;Para obtener una sintaxis completa de declaración de variables de cursor, consulte Referencia de lenguaje PL/SQL de Oracle Database.
-
Declare un registro que va a contener la fila devuelta por el cursor:
record_name return_type;Para obtener información completa sobre la sintaxis de declaración de registros, consulte Referencia de lenguaje PL/SQL de Oracle Database.
-
-
En la parte ejecutable:
-
Abra la variable de cursor para una consulta concreta:
OPEN cursor_variable FOR query;Para obtener información completa sobre la sintaxis de la sentencia OPEN FOR, consulte Referencia de lenguaje PL/SQL de Oracle Database.
-
Recupere una a las filas de la variable de cursor (filas del juego de resultados) de una en una, con una sentencia LOOP cuya sintaxis es similar a la siguiente:
LOOP FETCH cursor_variable INTO record_name; EXIT WHEN cursor_variable%NOTFOUND; -- Process row that is in record_name: statement; [ statement; ]... END LOOP;Para obtener información completa sobre la sintaxis de sentencias FETCH, consulte Referencia de lenguaje PL/SQL de Oracle Database.
-
Cierre la variable de cursor:
CLOSE cursor_variable;Como alternativa, puede abrir la variable de cursor para otra consulta, lo que la cerrará para la consulta actual.
Para obtener información completa sobre la sintaxis de las sentencias CLOSE, consulte Referencia de lenguaje PL/SQL de Oracle Database.
-
Tutorial: Uso de una Variable de Cursor para Recuperar Filas de Juegos de Resultados una a una
En los siguientes pasos se muestra cómo cambiar el procedimiento EMP_EVAL.EVAL_DEPARTMENT para que utilice una variable de cursor en lugar de un cursor declarado (que le permite procesar varios departamentos) y cómo hacer que EMP_EVAL.EVAL_DEPARTMENT y EMP_EVAL.ADD_EVAL sean más eficientes.
Cómo hacer que EMP_EVAL.EVAL_DEPARTMENT y EMP_EVAL.ADD_EVAL sean más eficaces: En lugar de transferir a ADD_EVAL un campo de un registro y tener ADD_EVAL utilizar tres consultas para extraer otros tres campos del mismo registro, EVAL_DEPARTMENT transfiere el registro entero a ADD_EVAL y ADD_EVAL utiliza la notación a puntos para acceder a los valores de otros tres campos.
Pasos para cambiar el procedimiento EMP_EVAL.EVAL_DEPARTMENT para que utilice una variable de cursor:
-
En la especificación de paquete EMP_EVAL, agregue la declaración del procedimiento y la definición de tipo REF CURSOR, como se muestra en el siguiente ejemplo:
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; -
En el cuerpo de paquete EMP_EVAL, agregue una declaración anticipada del procedimiento EVAL_LOOP_CONTROL y cambie la declaración del procedimiento ADD_EVAL, como se muestra en:
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); ...(Para ver un ejemplo detallado de cambio en un cuerpo del paquete, consulte "Tutorial: Declaración de Variables y Constantes en un Subprograma".)
-
Cambie el procedimiento EVAL_DEPARTMENT para recuperar tres juegos de resultado independientes basados en el departamento y para invocar al procedimiento EVAL_LOOP_CONTROL, como se muestra en el siguiente ejemplo:
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; -
Cambie el procedimiento ADD_EVAL como se muestra a continuación:
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; -
Antes de
END EMP_EVAL, agregue el procedimiento siguiente, que recupera los registros individuales del conjunto de resultados y los procesa: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; -
Antes de
END EMP_EVAL, agregue el procedimiento siguiente, que recupera un juego de resultado que contiene todos los empleados de la compañía: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; -
Compile la especificación de paquete
EMP_EVAL. -
Compile el cuerpo de paquete
EMP_EVAL.