it-swarm.it

Qual è la differenza tra i cursori espliciti e impliciti in Oracle?

Sono un po 'arrugginito sul mio cursore lingo in PL/SQL. Qualcuno lo sa?

25
Brian G

Un cursore implicito è uno creato "automaticamente" per te da Oracle quando si esegue una query. È più semplice da codificare, ma soffre di 

  • inefficienza (lo standard ANSI specifica che deve essere recuperato due volte per verificare se c'è più di un record)
  • vulnerabilità agli errori di dati (se si ottengono due righe, solleva un'eccezione TOO_MANY_ROWS)

Esempio

SELECT col INTO var FROM table WHERE something;

Un cursore esplicito è uno che crei te stesso. Richiede più codice, ma dà più controllo - ad esempio, puoi semplicemente aprire-recuperare-chiudere se vuoi solo il primo record e non importa se ce ne sono altri. 

Esempio

DECLARE   
  CURSOR cur IS SELECT col FROM table WHERE something; 
BEGIN
  OPEN cur;
  FETCH cur INTO var;
  CLOSE cur;
END;
39
Sten Vesterli

Un cursore esplicito è definito come tale in un blocco di dichiarazione:

DECLARE 
CURSOR cur IS 
  SELECT columns FROM table WHERE condition;
BEGIN
...

un cursore implicito è impiantato direttamente in un blocco di codice:

...
BEGIN
   SELECT columns INTO variables FROM table where condition;
END;
...
16
stjohnroe

1.CURSOR: Quando PLSQL emette istruzioni SQL, crea un'area di lavoro privata per analizzare ed eseguire l'istruzione sql si chiama cursore.

2.IMPLICIT: quando un blocco PL/SQL eseguibile emette un'istruzione sql . PL/SQL crea un cursore implicito e gestisce automaticamente i mezzi implcit open & close ha luogo. Usato quando l'istruzione sql restituisce solo una riga. Ha 4 attributi SQL% ROWCOUNT, SQL% FOUND, SQL% NOTFOUND, SQL% ISOPEN.

3. ESPLICITO: è creato e gestito dal programmatore. Ha bisogno di ogni tempo esplicito aperto, recupero e chiusura. Viene utilizzato quando sql statement restituisce più di una riga. Ha anche 4 attributi CUR_NAME% ROWCOUNT, CUR_NAME% FOUND, CUR_NAME% NOTFOUND, CUR_NAME% IsOpen. Elabora diverse righe usando il ciclo. Il programmatore può anche passare il parametro al cursore esplicito.

  • Esempio: Cursore esplicito

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;
4
Ganesh Pathare

I cursori impliciti richiedono memoria buffer anonima. 

I cursori espliciti possono essere eseguiti ancora e ancora usando il loro nome. Sono memorizzati nello spazio di memoria definito dall'utente invece di essere memorizzati in una memoria buffer anonima e quindi possono essere facilmente accessibili successivamente.

3
prince
3
pablo

Un cursore esplicito è quello che dichiari, come:

CURSOR my_cursor IS
  SELECT table_name FROM USER_TABLES

Un cursore implicito è uno creato per supportare qualsiasi SQL in linea che scrivi (statico o dinamico).

3
Dave Costa

In risposta alla prima domanda. Direttamente da Oracle documentazione

Un cursore è un puntatore a un SQL privato area che memorizza informazioni su elaborare uno specifico SELECT o DML dichiarazione.

3
Ian Carpenter

Con cursori espliciti, hai il controllo completo su come accedere alle informazioni nel database. Decidi quando aprire il cursore, quando FETCH registra dal cursore (e quindi dalla tabella o dalle tabelle nell'istruzione SELECT del cursore) quanti record recuperare e quando chiudere il cursore. Informazioni sullo stato attuale del cursore sono disponibili attraverso l'esame degli attributi del cursore.

Vedi http://www.unix.com.ua/orelly/Oracle/prog2/ch06_03.htm per i dettagli.

2
Kristian

Un cursore è una finestra SELEZIONATA su una tabella Oracle, questo significa un gruppo di record presenti in una tabella Oracle e che soddisfano determinate condizioni. Un cursore può SELEZIONARE anche tutto il contenuto di una tabella. Con un cursore puoi manipolare le colonne Oracle, aliasandole nel risultato. Un esempio di cursore implicito è il seguente:

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 si apre e si chiude il cursore automaticamente, quando tutti i record del cursore sono stati analizzati.

Un esempio di cursore esplicito è il seguente:

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;
/

Nel cursore esplicito si apre e si chiude il cursore in modo esplicito, controllando la presenza di record e dichiarando una condizione di uscita.

1
UltraCommit

Google è tuo amico: http://docstore.mik.ua/orelly/Oracle/prog2/ch06_03.htm

PL/SQL rilascia un cursore implicito ogni volta che si esegue un'istruzione SQL direttamente nel tuo codice, a condizione che il codice non utilizza un esplicito cursore. Si chiama "implicito" cursore perché tu, lo sviluppatore, fai non dichiarare esplicitamente un cursore per la dichiarazione SQL.

Un cursore esplicito è un SELECT dichiarazione che è esplicitamente definita nella sezione di dichiarazione del tuo codice e, nel processo, assegnato a nome. Non esiste una cosa come cursore esplicito per UPDATE, DELETE, e istruzioni INSERT.

1
Derek Swingley

Il cursore implicito restituisce solo un record e viene chiamato automaticamente. Tuttavia, i cursori espliciti sono chiamati manualmente e possono restituire più di un record.

1
shaiksyedbasha

So che questa è una vecchia domanda, tuttavia, penso che sarebbe opportuno aggiungere un esempio pratico per mostrare la differenza tra i due dal punto di vista delle prestazioni.

Dal punto di vista delle prestazioni, i cursori impliciti sono più veloci.

Vediamo la differenza di prestazioni tra i due:

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.

Quindi, una differenza significativa è chiaramente visibile.

Altri esempi qui .

1
Lalit Kumar B

Ad ogni istruzione SQL eseguita dal database Oracle è associato un cursore, che è un'area di lavoro privata per memorizzare le informazioni di elaborazione. I cursori impliciti vengono creati implicitamente dal server Oracle per tutte le istruzioni DML e SELECT.

È possibile dichiarare e utilizzare i cursori espliciti per denominare l'area di lavoro privata e accedere alle informazioni memorizzate nel blocco del programma.

0
ropable

Come indicato in altre risposte, i cursori impliciti sono più facili da usare e meno soggetti a errori. 

E Cursori impliciti o espliciti in Oracle PL/SQL mostra che i cursori impliciti sono fino a due volte più veloci di quelli espliciti.

È strano che nessuno abbia ancora menzionato Implicita FOR LOOP Cursor :

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;

Un altro esempio su SO: PL/SQL FOR LOOP IMPLICIT CURSOR .

È molto più breve di una forma esplicita.

Ciò fornisce anche un bel workaround per aggiornare più tabelle da CTE .

0
Vadzim