Ricerca…


Sintassi

  • Cursore cursor_name Is your_select_statement
  • Cursore cursor_name (param TYPE) Is your_select_statement_using_param
  • PER x in ( your_select_statement ) LOOP ...

Osservazioni

I cursori dichiarati sono difficili da utilizzare e nella maggior parte dei casi si consiglia di utilizzare i loop FOR . Ciò che è molto interessante nei cursori rispetto ai semplici cicli FOR , è che è possibile parametrizzarli.

È meglio evitare di fare loop con PL / SQL e cursori invece di usare Oracle SQL comunque. Tuttavia, per le persone abituate al linguaggio procedurale, può essere molto più facile da capire.

Se si desidera verificare se esiste un record, e quindi fare cose diverse a seconda che il record esista o meno, allora ha senso usare le istruzioni MERGE nelle query ORACLE SQL pure invece di usare i loop del cursore. (Si noti che MERGE è disponibile solo nelle versioni Oracle> = 9i).

Cursore "FOR loop" parametrizzato

DECLARE
  CURSOR c_emp_to_be_raised(p_sal emp.sal%TYPE) IS 
    SELECT * FROM emp WHERE  sal < p_sal;
BEGIN
  FOR cRowEmp IN c_emp_to_be_raised(1000) LOOP
    dbms_Output.Put_Line(cRowEmp .eName ||' ' ||cRowEmp.sal||'... should be raised ;)');
  END LOOP;
END;
/

Cursore implicito "FOR loop"

BEGIN
  FOR x IN (SELECT * FROM emp WHERE sal < 100) LOOP
    dbms_Output.Put_Line(x.eName ||' '||x.sal||'... should REALLY be raised :D');
  END LOOP;
END;
/
  • Il primo vantaggio è che non c'è nessuna dichiarazione noiosa da fare (pensate a questa orribile cosa "CURSORE" che avete avuto nelle versioni precedenti)
  • il secondo vantaggio è che prima crei la tua query di selezione, poi quando hai ciò che vuoi, puoi immediatamente accedere ai campi della tua query ( x.<myfield> ) nel tuo loop PL / SQL
  • Il ciclo apre il cursore e recupera un record alla volta per ogni ciclo. Alla fine del ciclo il cursore è chiuso.
  • I cursori impliciti sono più veloci perché il lavoro dell'interprete cresce man mano che il codice aumenta. Meno codice e meno lavoro deve fare l'interprete.

Lavorare con SYS_REFCURSOR

SYS_REFCURSOR può essere utilizzato come tipo restituito quando è necessario gestire facilmente un elenco restituito non da una tabella, ma più specificamente da una funzione:

funzione che restituisce un cursore

CREATE OR REPLACE FUNCTION list_of (required_type_in IN VARCHAR2)
   RETURN SYS_REFCURSOR
IS
   v_ SYS_REFCURSOR;
BEGIN
   CASE required_type_in
      WHEN 'CATS'
      THEN
         OPEN v_ FOR
           SELECT nickname FROM (
                select 'minou' nickname from dual
      union all select 'minâ'           from dual
      union all select 'minon'          from dual         
           );
      WHEN 'DOGS'
      THEN
         OPEN v_ FOR
              SELECT dog_call FROM (
                select 'bill'   dog_call from dual
      union all select 'nestor'          from dual
      union all select 'raoul'           from dual         
           );
   END CASE;
   -- Whit this use, you must not close the cursor.
   RETURN v_;
END list_of;
/

e come usarlo:

DECLARE
   v_names   SYS_REFCURSOR;
   v_        VARCHAR2 (32767);
BEGIN
   v_names := list_of('CATS');
   LOOP
      FETCH v_names INTO v_;
      EXIT WHEN v_names%NOTFOUND;
      DBMS_OUTPUT.put_line(v_);
   END LOOP;
   -- here you close it
   CLOSE v_names;
END;
/

Gestire un CURSORE

  • Dichiarare il cursore per eseguire la scansione di un elenco di record
  • Aprilo
  • Recupera il record corrente in variabili (questa incrementa la posizione)
  • Usa %notfound per rilevare la fine dell'elenco
  • Non dimenticare di chiudere il cursore per limitare il consumo di risorse nel contesto corrente

-

DECLARE
  CURSOR curCols IS -- select column name and type from a given table
         SELECT column_name, data_type FROM all_tab_columns where table_name='MY_TABLE';
  v_tab_column all_tab_columns.column_name%TYPE;
  v_data_type all_tab_columns.data_type%TYPE;
  v_ INTEGER := 1;
BEGIN
  OPEN curCols;
  LOOP
     FETCH curCols INTO v_tab_column, v_data_type;
     IF curCols%notfound OR v_ > 2000 THEN
       EXIT;
     END IF;
     dbms_output.put_line(v_||':Column '||v_tab_column||' is of '|| v_data_type||' Type.');
     v_:= v_ + 1;
  END LOOP;

  -- Close in any case
  IF curCols%ISOPEN THEN  
     CLOSE curCols;
  END IF;
END;
/


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow