1. PL/SQL – Interazioni col DB
PL/SQL è integrato completamente con Oracle, quindi è
possibile eseguire tutte le operazioni sui dati e sugli oggetti
del database.
2. Transazioni
COMMIT: salva tutti i cambiamenti dall’ultimo COMMIT o ROLLBACK
ROLLBACK: annulla tutti i cambiamenti dall’ultimo COMMIT o ROLLBACK
ROLLBACK TO SAVEPOINT name: annulla tutti i cambiamenti dal Savepoint
SAVEPOINT name: Crea un Savepoint
SET TRANSACTION type: permette di inizre una sessione READ ONLY, READ WRITE
o con impostazioni avanzate
LOCK TABLE name IN mode: permette di blocare una tabella con una certa modalità
3. CURSORI
Un cursore è un riferimento all’area di lavoro associata con un’istruzione
SQL.
I cursori possono essere impliciti o espliciti, ma nel seguito considereremo
solo quelli espliciti.
CURSOR employee_cur IS SELECT * FROM employee;
Il cursore poi può essere aperto:
OPEN employee_cur;
Quindi si possono recuperare dei dati con un FETCH:
FETCH employee_cur INTO employee_rec;
Infine il cursore si può chiudere
CLOSE employee_cur;
4. Cursori con e senza parametri
Senza parametri
CURSOR company_cur IS
SELECT company_id FROM company;
Con parametri (permette di filtrare i dati estratti)
CURSOR name_cur (company_id_in IN NUMBER)
IS
SELECT name FROM company
WHERE company_id = company_id_in;
Con tipo di ritorno
CURSOR emp_cur RETURN employee%ROWTYPE
IS
SELECT * FROM employee
WHERE department_id = 10;
5. Variabili nei cursori
DECLARE
/* A local PL/SQL variable */
projected_bonus NUMBER := 1000;
/*Cursor adds $1000 to the salary of each employee hired more than 3 years ago.*/
CURSOR employee_cur
IS
SELECT employee_id,
salary + projected_bonus new_salary, /* Column alias */
:review.evaluation /* Bind variable */
FROM employee
WHERE hiredate < ADD_MONTHS (SYSDATE, −36);
(Le variabili non possono avere lo stesso nome delle colonne delle tabelle)
6. Apertura dei cursori
L’apertura di un cursore avviene semplicemente con
l’istruzione OPEN, eventualmente passandogli dei parametri,
tuttavia è opportuno testare che il cursore non sia stato già
aperto:
IF NOT company_cur%ISOPEN
THEN
OPEN company_cur;
END IF;
7. Fetching dei cursori
Il cursore è un indice su una tabella virtuale recuperata da
una SELECT. Per recuperare i dati nelle righe selezionate si
deve operareb un FETCH.
FETCH company_cur INTO company_rec;
Il fetch può avvenire verso record, verso
variabili ‘scalari’ o anche verso variabili
di tipo %ROWTYPE.
L’operazione di fetch è possibile fino a che
non si supera l’ultima riga dopo di che
l’attributo %NOTFOUND avrà il valore TRUE
8. Alias per le colonne
DECLARE
CURSOR comp_cur IS
SELECT company_name, SUM (inv_amt) total_sales
FROM company C, invoice I
WHERE C.company_id = I.company_id
AND I.invoice_date BETWEEN '01 JAN 1994' AND '31 DEC 1994';− − − −
comp_rec comp_cur%ROWTYPE;
BEGIN
OPEN comp_cur;
FETCH comp_cur INTO comp_rec;
...
IF comp_rec.total_sales > 5000
THEN
DBMS_OUTPUT.PUT_LINE
(' You have exceeded your credit limit of
$5000 by ' ||
TO_CHAR (5000 company_rec.total_sales,−
'$9999'));
END IF;
END;
9. Attributi dei cursori
%FOUND TRUE se la riga viene recuperata correttamente
%NOTFOUND TRUE se la riga non viene recuperata
%ROWCOUNT Numero di righe recuperate
%ISOPEN TRUE se il cursore è aperto
Esempio di uso di FOUND
OPEN caller_cur;
LOOP
FETCH caller_cur INTO caller_rec;
EXIT WHEN NOT caller_cur%FOUND;
UPDATE call
SET caller_id = caller_rec.caller_id
WHERE call_timestamp < SYSDATE;
END LOOP;
CLOSE call_cur;
10. SELECT FOR UPDATE
L’operazione di SELECT non pone alcun lock sulle righe selezionate, ma il alcune case si
vuole apportare modifiche su tali righe e un blocco su esse diviene inevitabile: per ottenere
questo si aggiunge la clausola FOR UPDATE.
CURSOR toys_cur IS
SELECT name, manufacturer, preference_level,
sell_at_yardsale_flag
FROM my_sons_collection
WHERE hours_used = 0
FOR UPDATE;
CURSOR fall_jobs_cur IS
SELECT task, expected_hours, tools_required,
do_it_yourself_flag
FROM winterize
WHERE year = TO_CHAR (SYSDATE, 'YYYY')
FOR UPDATE OF task;
Il rilascio del blocco su una riga avviene all’atto dell’esecuzione
del COMMIT sul UPDATE che riguarda la riga stessa.
11. FOR per i CURSORI
Il ciclo for può essere usato in modo molto utili per scorrere i cursori all’interno dei loro limiti:
DECLARE
CURSOR occupancy_cur IS
SELECT pet_id, room_number
FROM occupancy WHERE occupied_dt = SYSDATE;
BEGIN
FOR occupancy_rec IN occupancy_cur
LOOP
update_bill (occupancy_rec.pet_id,
occupancy_rec.room_number);
END LOOP;
END;
12. Exception Handling
La gestione delle Eccezioni in PLSQL è molto efficiente e simile a quella realizzata in linguaggi come
java, e .NET.
La struttura di un programma è:
DECLARE
... declarations ...
BEGIN
... executable statements ...
[ EXCEPTION
... exception handlers ... ]
END;
Il blocco EXCEPTION ha il seguente formato:
EXCEPTION
WHEN NO_DATA_FOUND
THEN
executable_statements1;
WHEN payment_overdue
THEN
executable_statements2;
WHEN OTHERS
THEN
executable_statements3;
END;
13. Eccezioni standard
Oracle mette a disposizione numerosi tipi di eccezioni predefinite, di sistema.
CURSOR_ALREADY_OPEN
DUP_VAL_ON_INDEX
INVALID_CURSOR
INVALID_NUMBER
LOGIN_DENIED
NO_DATA_FOUND
NOT_LOGGED_ON
……
L’utente può comunque definire delle eccezioni personalizzate
14. Eccezioni personalizzate
E’ possibile dichiarare una variabile di tipo EXCEPTION
overdue_balance EXCEPTION;
BEGIN
... executable statements ...
LOOP
...
IF ... THEN
RAISE overdue_balance;
END IF;
END LOOP;
EXCEPTION
WHEN overdue_balance THEN ...
END;