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