Nel capitolo precedente abbiamo visto i cursori, più specificatamente abbiamo visto cosa sono e come si utilizzano i cursori espliciti. Esiste, tuttavia, un altro tipo di cursori, i cosiddetti cursori impliciti, che in realtà abbiamo già utilizzato pur senza saperlo. Infatti, ogni qualvolta eseguiamo un comando DML così come una query del tipo SELECT INTO, il server Oracle apre un cursore implicito. Tale tipo di cursore viene gestito automaticamente e, pertanto, non si devono usare i comandi OPEN, FETCH o CLOSE visti in precedenza per i cursori espliciti. Così come abbiamo visto accadere per i cursori espliciti, anche per i cursori impliciti Oracle mette a disposizione una serie di attributi per una migliore gestione:
- SQL%ISOPEN – booleano, ritorna sempre FALSE in quanto chiude i cursori impliciti immediatamente dopo la loro esecuzione
- SQL%FOUND – booleano, ritorna TRUE se l’ultimo comando SQL ha restituito delle righe
- SQL%NOTFOUND – booleano, ritorna TRUE se l’ultimo comando SQL non ha restituito delle righe
- SQL%ROWCOUNT – numerico, ritorna il numero totale di righe restituite dall’ultimo comando SQL
DECLARE
Nome varchar2(80);
BEGIN
SELECT nome
INTO Nome
FROM anagrafica
WHERE cognome = 'ROSSI';
IF SQL%NOTFOUND THEN
INSERT INTO Log(messaggio)
VALUES ('Nessuna ricorrenza.');
END IF;
END;
In sostanza, se la nostra query non restituisce nessuna occorrenza, viene inserito un messaggio di errore nella nostra tabella Log.
Dopo questo breve accenno ai cursori impliciti, torniamo ancora sui cursori espliciti che stavamo trattando nel precedente capitolo. Abbiamo visto che, dopo aver definito un cursore, per gestirlo abbiamo bisogno di diversi comandi, ovvero abbiamo bisogno dei comandi OPEN, FETCH e CLOSE. Vedremo ora come, combinando l’utilizzo dei cursori con quello di un ciclo FOR, la gestione del cursore viene semplificata notevolmente. Avremo infatti che il ciclo FOR dichiara implicitamente un indice del loop come record %ROWTYPE avente la stessa struttura del cursore, apre il cursore, legge i valori e, infine, chiude il cursore quando sono state processate tutte le righe estratte. Vediamo come si presenterebbe il nostro blocco:
DECLARE
...;
CURSOR cur_anagrafica IS
SELECT nome, cognome, stipendio, ruolo
FROM anagrafica;
totale_stipendi NUMBER := 0;
BEGIN
Istruzione1;
FOR rec_anagrafica IN cur_anagrafica LOOP
totale_stipendi := totale_stipendi + rec_anagrafica.stipendio;
END LOOP;
END;
In pratica il ciclo FOR si occupa di tutte quelle incombenze cui generalmente dobbiamo pensare noi.
Volendo, possiamo anche evitare di definire il cursore prima dell’ingresso nel LOOP specificando direttamente la query al posto del cursore. In tal caso il nostro blocco si presenterebbe così:
DECLARE
...;
totale_stipendi NUMBER := 0;
BEGIN
Istruzione1;
FOR rec_anagrafica in (SELECT Nome, Cognome, Stipendio, Ruolo
FROM Anagrafica;) LOOP
totale_stipendi := totale_stipendi + rec_anagrafica.stipendio;
END LOOP;
END;