¿Qué sentencia debo utilizar? ¿For loop? ¿Loop Fetch?
Para saber cuál utilizar dentro del curso hay que siempre tener el performance que tendrá el cursor.
FOR LOOP.- Utilizar un CURSOR FOR LOOP cuando desea buscar y procesar todos los registros en un cursor. El CURSOR FOR LOOP finalizará cuando todos los registros del cursor hayan sido obtenidos.
Es una buena alternativa para utilizar con el cursor por lo que no es necesario abrir ni cerrar el cursor, inicia cuando la instrucción da orden de iniciar y cierra cuando finaliza todo el registro.
Ejemplo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
CREATE OR REPLACE FUNCTION F_SUMAR_INGRESO_MENSUAL(P_CODIGOEMPLEADO IN EMPLEADO.CODIGOEMPLEADO%TYPE) RETURN NUMBER IS NTOTAL NUMBER(12,2); CURSOR C1 IS SELECT IMPORTE_MENSUAL FROM EMPLEADO WHERE CODIGOEMPLEADO = P_CODIGOEMPLEADO; BEGIN NTOTAL := 0; FOR N IN C1 LOOP NTOTAL := NTOTAL + N.IMPORTE_MENSUAL; END LOOP; RETURN NTOTAL; END F_SUMAR_INGRESO_MENSUAL; |
LOOP FETCH.- Las variables deben coincidir (tanto en número como en posición) las columnas enumeradas en la definición del cursor.
También los tipos de datos deben coincidir o ser compatibles.
Una instrucción fetch recupera las filas una a la vez del conjunto de resultados de una consulta de varias filas; en otras palabras, avanza el cursor a la siguiente fila.
— Abrir un cursor sólo si es necesario
1 2 3 |
IF NOT C1%ISOPEN THEN OPEN C1; END IF; |
— Obtener un máximo de 20 registros (o menos si la tabla es menor)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
CREATE OR REPLACE FUNCTION F_SUMAR_INGRESO_MENSUAL(P_CODIGOEMPLEADO IN EMPLEADO.CODIGOEMPLEADO%TYPE) RETURN NUMBER IS NTOTAL NUMBER(12,2); CURSOR C1 IS SELECT IMPORTE_MENSUAL FROM EMPLEADO WHERE CODIGOEMPLEADO = P_CODIGOEMPLEADO; NIMPORTE_MENSUAL EMPLEADO.IMPORTE_MENSUAL%TYPE; BEGIN NTOTAL := 0; OPEN C1; LOOP FETCH C1 INTO NIMPORTE_MENSUAL; EXIT WHEN C1%ROWCOUNT > 20 OR C1%NOTFOUND; NTOTAL := NTOTAL + NIMPORTE_MENSUAL; END LOOP; CLOSE C1; RETURN NTOTAL; END F_SUMAR_INGRESO_MENSUAL; |
— Haciendo esto un paso más allá, buscando en una variable ROWTYPE Record
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
CREATE OR REPLACE FUNCTION F_SUMAR_INGRESO_MENSUAL(P_CODIGOEMPLEADO IN EMPLEADO.CODIGOEMPLEADO%TYPE) RETURN NUMBER IS NTOTAL NUMBER(12,2); CURSOR C1 IS SELECT IMPORTE_MENSUAL, CODIGOEMPLEADO FROM EMPLEADO WHERE CODIGOEMPLEADO = P_CODIGOEMPLEADO; CCURSOR C1%ROWTYPE; BEGIN NTOTAL := 0; OPEN C1; LOOP FETCH C1 INTO CCURSOR; EXIT WHEN C1%NOTFOUND; IF CCURSOR.CODIGOEMPLEADO = 200 THEN NTOTAL := NTOTAL + CCURSOR.IMPORTE_MENSUAL; ELSE NTOTAL := 0; END IF; END LOOP; CLOSE C1; RETURN NTOTAL; END F_SUMAR_INGRESO_MENSUAL; |
Conclusiones
En lo personal recomiendo utilizar FOR LOOP, por lo mismo que el código es reducido y haciendo una comparación de performance efectivamente el for loop lleva la ventaja, además no es necesario abrir y cerrar el cursor para utilizarlo. LOOP FETCH lo utilizo como última instancia.