vacio - recorrer cursor oracle
¿Cuál es la diferencia entre los cursores explícitos e implícitos en Oracle? (15)
Estoy un poco oxidado en mi jerga de cursor en PL / SQL. Alguien sabe esto?
Un cursor explícito es uno que declaras, como:
CURSOR my_cursor IS
SELECT table_name FROM USER_TABLES
Un cursor implícito es uno creado para admitir cualquier SQL en línea que escriba (ya sea estático o dinámico).
Un cursor explícito se define como tal en un bloque de declaración:
DECLARE
CURSOR cur IS
SELECT columns FROM table WHERE condition;
BEGIN
...
un cursor implícito se implementa directamente en un bloque de código:
...
BEGIN
SELECT columns INTO variables FROM table where condition;
END;
...
Con los cursores explícitos, tiene control total sobre cómo acceder a la información en la base de datos. Usted decide cuándo ABRIR el cursor, cuando FETCH registra desde el cursor (y por lo tanto desde la tabla o tablas en la instrucción SELECT del cursor) cuántos registros recuperar y cuándo CERRAR el cursor. La información sobre el estado actual de su cursor está disponible mediante el examen de los atributos del cursor.
Ver http://www.unix.com.ua/orelly/oracle/prog2/ch06_03.htm para más detalles.
Cada instrucción SQL ejecutada por la base de datos Oracle tiene un cursor asociado, que es un área de trabajo privada para almacenar información de procesamiento. Los cursores implícitos son creados implícitamente por el servidor Oracle para todas las sentencias DML y SELECT.
Puede declarar y usar cursores explícitos para nombrar el área de trabajo privada y acceder a su información almacenada en su bloque de programa.
En estos días, los cursores implícitos son más eficientes que los cursores explícitos.
http://www.oracle.com/technology/oramag/oracle/04-sep/o54plsql.html
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:1205168148688
Explícito...
cursor foo es select * from blah; comenzar la salida de búsqueda abierta cuando el cursor cercano yada yada yada
no los uses, usa implícito
cursor foo es select * from blah;
para n en foo loop x = n.some_column end loop
Creo que incluso puedes hacer esto
para n en (seleccione * de bla) ciclo ...
Se adhieren a lo implícito, se cierran a sí mismos, son más legibles, hacen la vida más fácil.
Un cursor implícito es uno creado "automáticamente" para usted por Oracle cuando ejecuta una consulta. Es más simple codificar, pero sufre de
- ineficiencia (el estándar ANSI especifica que debe buscar dos veces para verificar si hay más de un registro)
- vulnerabilidad a los errores de datos (si alguna vez obtiene dos filas, se genera una excepción TOO_MANY_ROWS)
Ejemplo
SELECT col INTO var FROM table WHERE something;
Un cursor explícito es uno que creas tú mismo. Se necesita más código, pero le da más control; por ejemplo, puede abrir-buscar-cerrar si solo quiere el primer registro y no le importa si hay otros.
Ejemplo
DECLARE
CURSOR cur IS SELECT col FROM table WHERE something;
BEGIN
OPEN cur;
FETCH cur INTO var;
CLOSE cur;
END;
En respuesta a la primera pregunta. Directamente de la documentación de Oracle
Un cursor es un puntero a un área privada de SQL que almacena información sobre el procesamiento de una instrucción SELECT o DML específica.
Google es tu amigo: http://docstore.mik.ua/orelly/oracle/prog2/ch06_03.htm
PL / SQL emite un cursor implícito cada vez que ejecuta una instrucción SQL directamente en su código, siempre que ese código no emplee un cursor explícito. Se denomina cursor "implícito" porque usted, el desarrollador, no declara explícitamente un cursor para la instrucción SQL.
Un cursor explícito es una declaración SELECT que se define explícitamente en la sección de declaración de su código y, en el proceso, le asigna un nombre. No existe un cursor explícito para las instrucciones UPDATE, DELETE e INSERT.
Un cursor es una ventana SELECCIONADA en una tabla de Oracle, esto significa un grupo de registros presentes en una tabla de Oracle y que cumplen ciertas condiciones. Un cursor también puede SELECCIONAR todo el contenido de una tabla. Con un cursor puede manipular las columnas de Oracle, aliasing en el resultado. Un ejemplo de cursor implícito es el siguiente:
BEGIN
DECLARE
CURSOR C1
IS
SELECT DROPPED_CALLS FROM ALARM_UMTS;
C1_REC C1%ROWTYPE;
BEGIN
FOR C1_REC IN C1
LOOP
DBMS_OUTPUT.PUT_LINE (''DROPPED CALLS: '' || C1_REC.DROPPED_CALLS);
END LOOP;
END;
END;
/
Con FOR ... LOOP ... END LOOP abre y cierra el cursor automáticamente, cuando se han analizado todos los registros del cursor.
Un ejemplo de cursor explícito es el siguiente:
BEGIN
DECLARE
CURSOR C1
IS
SELECT DROPPED_CALLS FROM ALARM_UMTS;
C1_REC C1%ROWTYPE;
BEGIN
OPEN c1;
LOOP
FETCH c1 INTO c1_rec;
EXIT WHEN c1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE (''DROPPED CALLS: '' || C1_REC.DROPPED_CALLS);
END LOOP;
CLOSE c1;
END;
END;
/
En el cursor explícito, abre y cierra el cursor de una manera explícita, verificando la presencia de registros y estableciendo una condición de salida.
1.CURSOR: Cuando PLSQL emite sentencias SQL, crea un área de trabajo privada para analizar y ejecutar la instrucción sql que se llama cursor.
2.IMPLICIT: cuando cualquier bloque PL / SQLexecutable emite instrucción sql. PL / SQL crea cursor implícito y se gestiona automáticamente significa que se produce implcit open & close. Se usa cuando la sentencia sql devuelve solo una fila. Tiene 4 atributos SQL% ROWCOUNT, SQL% FOUND, SQL% NOTFOUND, SQL% ISOPEN.
3.EXPLICIT: es creado y administrado por el programador. Necesita cada vez abrir, abrir y cerrar explícitamente. Se usa cuando la instrucción sql devuelve más de una fila. También tiene 4 atributos CUR_NAME% ROWCOUNT, CUR_NAME% FOUND, CUR_NAME% NOTFOUND, CUR_NAME% ISOPEN. Procesa varias filas mediante el uso de bucle. El programador puede pasar el parámetro también al cursor explícito.
- Ejemplo: Cursor explícito
declare
cursor emp_cursor
is
select id,name,salary,dept_id
from employees;
v_id employees.id%type;
v_name employees.name%type;
v_salary employees.salary%type;
v_dept_id employees.dept_id%type;
begin
open emp_cursor;
loop
fetch emp_cursor into v_id,v_name,v_salary,v_dept_id;
exit when emp_cursor%notfound;
dbms_output.put_line(v_id||'', ''||v_name||'', ''||v_salary||'',''||v_dept_id);
end loop;
close emp_cursor;
end;
El cursor implícito solo devuelve un registro y se invoca automáticamente. Sin embargo, los cursores explícitos se llaman manualmente y pueden devolver más de un registro.
Los cursores implícitos requieren memoria de búfer anónima.
Los cursores explícitos se pueden ejecutar una y otra vez usando su nombre. Se almacenan en un espacio de memoria definido por el usuario en lugar de almacenarse en una memoria anónima de búfer y, por lo tanto, se puede acceder fácilmente después.
Sé que esta es una vieja pregunta, sin embargo, creo que sería bueno agregar un ejemplo práctico para mostrar la diferencia entre los dos desde el punto de vista del rendimiento.
Desde el punto de vista del rendimiento, los cursores implícitos son más rápidos.
Veamos la diferencia de rendimiento entre los dos:
SQL> SET SERVEROUTPUT ON
SQL> DECLARE
2 l_loops NUMBER := 100000;
3 l_dummy dual.dummy%TYPE;
4 l_start NUMBER;
5
6 CURSOR c_dual IS
7 SELECT dummy
8 FROM dual;
9 BEGIN
10 l_start := DBMS_UTILITY.get_time;
11
12 FOR i IN 1 .. l_loops LOOP
13 OPEN c_dual;
14 FETCH c_dual
15 INTO l_dummy;
16 CLOSE c_dual;
17 END LOOP;
18
19 DBMS_OUTPUT.put_line(''Explicit: '' ||
20 (DBMS_UTILITY.get_time - l_start) || '' hsecs'');
21
22 l_start := DBMS_UTILITY.get_time;
23
24 FOR i IN 1 .. l_loops LOOP
25 SELECT dummy
26 INTO l_dummy
27 FROM dual;
28 END LOOP;
29
30 DBMS_OUTPUT.put_line(''Implicit: '' ||
31 (DBMS_UTILITY.get_time - l_start) || '' hsecs'');
32 END;
33 /
Explicit: 332 hsecs
Implicit: 176 hsecs
PL/SQL procedure successfully completed.
Entonces, una diferencia significativa es claramente visible.
Más ejemplos aquí .
Como se indica en otras respuestas, los cursores implícitos son más fáciles de usar y menos propensos a errores.
Y cursores implícitos frente a explícitos en Oracle PL / SQL muestra que los cursores implícitos son hasta dos veces más rápidos que los explícitos también.
Es extraño que nadie haya mencionado el Cursor FOR LOOP implícito :
begin
for cur in (
select t.id from parent_trx pt inner join trx t on pt.nested_id = t.id
where t.started_at > sysdate - 31 and t.finished_at is null and t.extended_code is null
)
loop
update trx set finished_at=sysdate, extended_code = -1 where id = cur.id;
update parent_trx set result_code = -1 where nested_id = cur.id;
end loop cur;
end;
Otro ejemplo en SO: PL / SQL FOR LOOP IMPLICIT CURSOR .
Es mucho más corto que la forma explícita.
Esto también proporciona una buena solución para actualizar varias tablas de CTE .