Oracle PL/SQL BULK COLLECT: Esempio FORALL
โก Riepilogo intelligente
RITIRO ALL'INGROSSO in Oracle PL/SQL recupera molte righe contemporaneamente in una collection, mentre FORALL invia operazioni DML in blocco al database. Entrambi riducono i cambi di contesto tra i motori SQL e PL/SQL, migliorando le prestazioni.

Cos'รจ il BULK COLLECT?
BULK COLLECT riduce i cambi di contesto tra SQL e motore PL/SQL e consente al motore SQL di recuperare i record in una sola volta.
Oracle PL / SQL fornisce la funzionalitร di recuperare i record in blocco anzichรฉ recuperarli uno per uno. Questo BULK COLLECT puรฒ essere utilizzato in un'istruzione SELECT per popolare i record in blocco o per recuperare un cursore in blocco. Poichรฉ BULK COLLECT recupera i record in blocco, la clausola INTO deve sempre contenere una variabile di tipo collezione. Il principale vantaggio dell'utilizzo di BULK COLLECT รจ che aumenta le prestazioni riducendo l'interazione tra il database e il motore PL/SQL.
Sintassi:
SELECT <column1> BULK COLLECT INTO bulk_variable FROM <table name>; FETCH <cursor_name> BULK COLLECT INTO <bulk_variable>;
Nella sintassi sopra riportata, BULK COLLECT viene utilizzato per raccogliere i dati dalle istruzioni SELECT e FETCH.
Clausola FORALL
L'istruzione FORALL esegue Operazioni DML sui dati in blocco. Assomiglia a un ciclo FOR, tranne per il fatto che in un ciclo FOR le azioni avvengono a livello di record, mentre in FORALL non esiste il concetto di ciclo. Invece, tutti i dati presenti nell'intervallo specificato vengono elaborati contemporaneamente.
Sintassi:
FORALL <loop_variable> in <lower range> .. <higher range>
<DML operations>;
Nella sintassi sopra riportata, l'operazione DML specificata verrร eseguita sull'intera quantitร di dati presenti tra il limite inferiore e quello superiore.
Clausola LIMITE
Il concetto di "bulk collect" carica tutti i dati nella variabile di destinazione in blocco, ovvero tutti i dati vengono inseriti nella variabile in un'unica operazione. Tuttavia, questo approccio non รจ consigliabile quando il numero totale di record da caricare รจ molto elevato, perchรฉ quando PL/SQL tenta di caricare tutti i dati consuma piรน memoria di sessione. Pertanto, รจ sempre opportuno limitare le dimensioni di questa operazione di "bulk collect".
Questo limite di dimensione puรฒ essere facilmente raggiunto introducendo la condizione ROWNUM nell'istruzione SELECT, mentre nel caso di un cursore ciรฒ non รจ possibile.
Per superare questo, Oracle ha fornito la clausola LIMIT che definisce il numero di record che devono essere inclusi nel blocco.
Sintassi:
FETCH <cursor_name> BULK COLLECT INTO <bulk_variable> LIMIT <size>;
Nella sintassi sopra riportata, l'istruzione di recupero del cursore utilizza l'istruzione BULK COLLECT insieme alla clausola LIMIT.
Attributi BULK COLLECT
Analogamente agli attributi del cursore, BULK COLLECT ha %BULK_ROWCOUNT(n) che restituisce il numero di righe interessate nell'n-esima istruzione DML dell'istruzione FORALL, ovvero fornisce il conteggio dei record interessati nell'istruzione FORALL per ogni singolo valore della variabile di raccolta. Il termine 'n' indica la sequenza del valore nella raccolta per cui รจ necessario il conteggio delle righe.
Esempio 1: In questo esempio, proietteremo tutti i nomi dei dipendenti dalla tabella emp utilizzando BULK COLLECT e aumenteremo anche lo stipendio di tutti i dipendenti di 5000 utilizzando FORALL.
Lo screenshot qui sotto mostra questo esempio BULK COLLECT e FORALL insieme al suo output in Oracle.
DECLARE CURSOR guru99_det IS SELECT emp_name FROM emp; TYPE lv_emp_name_tbl IS TABLE OF VARCHAR2(50); lv_emp_name lv_emp_name_tbl; BEGIN OPEN guru99_det; FETCH guru99_det BULK COLLECT INTO lv_emp_name LIMIT 5000; FOR c_emp_name IN lv_emp_name.FIRST .. lv_emp_name.LAST LOOP Dbms_output.put_line('Employee Fetched:'||c_emp_name); END LOOP; FORALL i IN lv_emp_name.FIRST .. lv_emp_name.LAST UPDATE emp SET salary=salary+5000 WHERE emp_name=lv_emp_name(i); COMMIT; Dbms_output.put_line('Salary Updated'); CLOSE guru99_det; END; /
Uscita
Employee Fetched:BBB Employee Fetched:XXX Employee Fetched:YYY Salary Updated
Code Spiegazione:
- Code riga 2: Dichiarazione del cursore guru99_det per l'istruzione 'SELECT emp_name FROM emp'.
- Code riga 3: Dichiarazione di lv_emp_name_tbl come tipo di tabella VARCHAR2(50).
- Code riga 4: Dichiarazione di lv_emp_name come tipo lv_emp_name_tbl.
- Code riga 6: Apertura del cursore.
- Code riga 7: Recupero del cursore tramite BULK COLLECT con dimensione LIMIT pari a 5000 nella variabile lv_emp_name.
- Code righe 8-11: Impostazione di un ciclo FOR per stampare tutti i record nella collezione lv_emp_name.
- Code riga 12: Utilizzo della funzione FORALL per aggiornare lo stipendio di tutti i dipendenti di 5000.
- Code riga 14: Commettere il delle transazioni.

