La sentència FORALL
en PL/SQL és una característica poderosa que permet executar operacions DML (Data Manipulation Language) en lots, millorant significativament el rendiment en comparació amb l'execució de les mateixes operacions dins d'un bucle FOR
. Aquesta sentència és especialment útil quan es treballa amb grans volums de dades.
Conceptes Clau
- Execució en Lots: La sentència
FORALL
permet executar múltiples operacions DML (INSERT, UPDATE, DELETE) en una sola instrucció, reduint el nombre de commutacions de context entre PL/SQL i SQL. - Índexs de Col·lecció: La sentència
FORALL
utilitza col·leccions (com ara arrays associatius, taules indexades o VARRAYs) per emmagatzemar els valors que s'utilitzaran en les operacions DML. - Millora del Rendiment: En reduir el nombre de commutacions de context, la sentència
FORALL
pot millorar significativament el rendiment de les operacions DML massives.
Sintaxi Bàsica
index
: És una variable que recorre els elements de la col·lecció.lower_bound
iupper_bound
: Defineixen el rang d'índexs de la col·lecció que es recorreran.sql_statement
: És l'operació DML que s'executarà per a cada element de la col·lecció.
Exemple Pràctic
Suposem que tenim una taula employees
i volem actualitzar els salaris de diversos empleats. Utilitzarem la sentència FORALL
per fer-ho de manera eficient.
Creació de la Taula i Inserció de Dades
CREATE TABLE employees ( employee_id NUMBER PRIMARY KEY, salary NUMBER ); INSERT INTO employees (employee_id, salary) VALUES (1, 5000); INSERT INTO employees (employee_id, salary) VALUES (2, 6000); INSERT INTO employees (employee_id, salary) VALUES (3, 7000); COMMIT;
Actualització de Salaris amb FORALL
DECLARE TYPE salary_array IS TABLE OF NUMBER INDEX BY PLS_INTEGER; new_salaries salary_array; BEGIN -- Emplenem la col·lecció amb els nous salaris new_salaries(1) := 5500; new_salaries(2) := 6500; new_salaries(3) := 7500; -- Utilitzem FORALL per actualitzar els salaris FORALL i IN new_salaries.FIRST..new_salaries.LAST UPDATE employees SET salary = new_salaries(i) WHERE employee_id = i; COMMIT; END; /
Explicació del Codi
- Declaració de la Col·lecció: Declarem una col·lecció
salary_array
per emmagatzemar els nous salaris. - Emplenament de la Col·lecció: Assignem els nous salaris als elements de la col·lecció.
- Sentència FORALL: Utilitzem
FORALL
per actualitzar els salaris en la taulaemployees
de manera eficient.
Exercici Pràctic
Enunciat
Crea una taula products
amb les columnes product_id
i price
. Utilitza la sentència FORALL
per actualitzar els preus de diversos productes.
Solució
-- Creació de la taula CREATE TABLE products ( product_id NUMBER PRIMARY KEY, price NUMBER ); -- Inserció de dades INSERT INTO products (product_id, price) VALUES (1, 100); INSERT INTO products (product_id, price) VALUES (2, 200); INSERT INTO products (product_id, price) VALUES (3, 300); COMMIT; -- Actualització de preus amb FORALL DECLARE TYPE price_array IS TABLE OF NUMBER INDEX BY PLS_INTEGER; new_prices price_array; BEGIN -- Emplenem la col·lecció amb els nous preus new_prices(1) := 110; new_prices(2) := 220; new_prices(3) := 330; -- Utilitzem FORALL per actualitzar els preus FORALL i IN new_prices.FIRST..new_prices.LAST UPDATE products SET price = new_prices(i) WHERE product_id = i; COMMIT; END; /
Errors Comuns i Consells
- Índexs No Contigus: Assegura't que els índexs de la col·lecció siguin contigus. Si no ho són, utilitza la clàusula
INDICES OF
oVALUES OF
. - Gestió d'Errors: Utilitza la clàusula
SAVE EXCEPTIONS
per capturar i gestionar errors durant l'execució de la sentènciaFORALL
.
Exemple amb SAVE EXCEPTIONS
DECLARE TYPE price_array IS TABLE OF NUMBER INDEX BY PLS_INTEGER; new_prices price_array; errors EXCEPTION; PRAGMA EXCEPTION_INIT(errors, -24381); BEGIN -- Emplenem la col·lecció amb els nous preus new_prices(1) := 110; new_prices(2) := 220; new_prices(3) := 330; -- Utilitzem FORALL amb SAVE EXCEPTIONS FORALL i IN new_prices.FIRST..new_prices.LAST SAVE EXCEPTIONS UPDATE products SET price = new_prices(i) WHERE product_id = i; COMMIT; EXCEPTION WHEN errors THEN FOR i IN 1..SQL%BULK_EXCEPTIONS.COUNT LOOP DBMS_OUTPUT.PUT_LINE('Error en l\'índex: ' || SQL%BULK_EXCEPTIONS(i).ERROR_INDEX); DBMS_OUTPUT.PUT_LINE('Codi d\'error: ' || SQL%BULK_EXCEPTIONS(i).ERROR_CODE); END LOOP; END; /
Conclusió
La sentència FORALL
és una eina essencial per a l'optimització de les operacions DML en PL/SQL. Permet executar operacions en lots, millorant el rendiment i reduint el temps d'execució. Amb la pràctica i la comprensió dels seus conceptes clau, podràs utilitzar FORALL
per gestionar grans volums de dades de manera eficient.
Curs de PL/SQL
Mòdul 1: Introducció a PL/SQL
Mòdul 2: Fonaments de PL/SQL
- Estructura del bloc PL/SQL
- Variables i tipus de dades
- Estructures de control
- Cursors
- Gestió d'excepcions