Oracle PL/SQL. Motivazioni



Похожие документы
PL/SQL PL/SQL. Ordine degli elementi dei triggers di Oracle. Differenze nei triggers. Versione dei trigger e PSM di Oracle

Basi di dati. Il Linguaggio SQL. K. Donno - Il Linguaggio SQL

Il linguaggio SQL: trigger. Versione elettronica: 04.7.SQL.trigger.pdf

Triggers. Basi dati attive. Trigger. Indipendenza della conoscenza

LA REALIZZAZIONE DI APPLICAZIONI ALCUNE ARCHITETTURE

LA REALIZZAZIONE DI APPLICAZIONI. Quattro parti: Gestione dati. Business rules. Logica applicativa. Interfaccia utente. Molte possibili architetture

Lezione 8. Metadati, Viste e Trigger

Insegnamento di Informatica CdS Scienze Giuridiche A.A. 2006/7. Il trattamento dei dati

Abilità Informatiche A.A. 2010/2011 Lezione 9: Query Maschere Report. Facoltà di Lingue e Letterature Straniere

Definizione di domini

Data Base. Master "Bio Info" Reti e Basi di Dati Lezione 6

APPENDICE. Procedure in SQL (1)

Giovanna Rosone 04/03/ /03/2010 SQL, Istruzioni per la modifica dello schema

Al giorno d oggi, i sistemi per la gestione di database

I file di dati. Unità didattica D1 1

Esercitazione query in SQL L esercitazione viene effettuata sul database viaggi e vacanze che prevede il seguente modello E/R:

Siti web centrati sui dati Architettura MVC-2: i JavaBeans

Il linguaggio SQL. è di fatto lo standard tra i linguaggi per la gestione di data base relazionali.

Il DBMS Oracle. Express Edition. Donatella Gubiani e Angelo Montanari

Linee guida per la programmazione di transazioni in PL/SQL

DDL, VINCOLI D INTEGRITÁ, AGGIORNAMENTI E VISTE. SQL è più di un semplice linguaggio di interrogazione

SQL prima parte D O C E N T E P R O F. A L B E R T O B E L U S S I. Anno accademico 2011/12

Il linguaggio SQL: viste e tabelle derivate

Capitolo 7. Esercizio 7.1

DBMS (Data Base Management System)

Come trattare il risultato di un comando SQL (relazioni) che

Il linguaggio SQL: viste e tabelle derivate. Versione elettronica: SQLd-viste.pdf

MANUALE UTENTE Fiscali Free

Tipi primitivi. Ad esempio, il codice seguente dichiara una variabile di tipo intero, le assegna il valore 5 e stampa a schermo il suo contenuto:

Uso delle variabili di alias. SQL slide aggiuntive. Interrogazione 25. Interrogazione 26

2104 volume III Programmazione

SQL Server. SQL server e un RDBMS di tipo client/server che utilizza Transact-SQL per gestire la comunicazione fra un client e SQL Server

Operazioni sui database

Architettura MVC-2: i JavaBeans

OSSIF WEB. Manuale query builder

DATABASE RELAZIONALI

Join in SQL (primo modo) Informatica. Tabella Dipartimento. Interrogazione 4a. Interrogazione 4b. Interrogazione 4a

Access. Microsoft Access. Aprire Access. Aprire Access. Aprire un database. Creare un nuovo database

GERARCHIE RICORSIVE - SQL SERVER 2008

Lezione 8. La macchina universale

Lezione 9. Applicazioni tradizionali

Riccardo Dutto, Paolo Garza Politecnico di Torino. Riccardo Dutto, Paolo Garza Politecnico di Torino

SQL/OLAP. Estensioni OLAP in SQL

Volumi di riferimento

4.1 FAX Sollecito consegne via (Nuova funzione)

Vincoli di Integrità Approccio dichiarativo alla loro implementazione

Database Lezione 1. Sommario. - Introduzione - Tabelle e chiave primaria - Query - Calcoli ed alias - Ordinamento

Informatica Generale Andrea Corradini Sistemi di Gestione delle Basi di Dati

Progettazione di Basi di Dati

Istruzioni DML di SQL

Suggerimenti per lo Sviluppo delle Applicazioni con PL/SQL. Simona Rotolo

PL/SQL Uso di un linguaggio procedurale per un database

ESEMPI DI QUERY SQL. Esempi di Query SQL Michele Batocchi AS 2012/2013 Pagina 1 di 7

Software Servizi Web UOGA

Finalità della soluzione Schema generale e modalità d integrazione Gestione centralizzata in TeamPortal... 6

Corso Sistemi Informativi Avanzati. Programma 30 set Installazione Macchina Virtuale. Introduzione alla BI nelle Aziende.

I comandi del linguaggio DDL (Data Definition Language): CREATE E ALTER

GESTIONE INFORMATICA DEI DATI AZIENDALI

Lezione V. Aula Multimediale - sabato 29/03/2008

LA GESTIONE DELLE VISITE CLIENTI VIA WEB

Dispensa di database Access

Dati relazionali e XML

Data warehouse in Oracle

Registratori di Cassa

Organizzazione degli archivi

INFORMATICA. Applicazioni WEB a tre livelli con approfondimento della loro manutenzione e memorizzazione dati e del DATABASE.

Basi di Dati: Corso di laboratorio

Raggruppamenti Conti Movimenti

SQL - Funzioni di gruppo

ALICE AMMINISTRAZIONE UTENTI WEB

SQL non è solo un linguaggio di interrogazione (Query Language), ma. Un linguaggio per la definizione di basi di dati (Data-definition language (DDL))

Progetto: ARPA Fonte Dati. ARPA Fonte Dati. Regione Toscana. Manuale Amministratore

I database relazionali (Access)

MANUALE PARCELLA FACILE PLUS INDICE

Regione Toscana. ARPA Fonte Dati. Manuale Amministratore. L. Folchi (TAI) Redatto da

RISOLUTORE AUTOMATICO PER SUDOKU

INFORMATICA 1 L. Mezzalira

Nozione ed uso. Operazioni eseguite automaticamente ogni volta che avviene un certo evento Uso:

Database Manager Guida utente DMAN-IT-01/09/10

Funzioni in C. Violetta Lonati

Esercitazione 02: JDBC, SQL e DB SAMPLE

Telerilevamento e GIS Prof. Ing. Giuseppe Mussumeci

3 - Variabili. Programmazione e analisi di dati Modulo A: Programmazione in Java. Paolo Milazzo

Uso delle basi di dati DBMS. Cos è un database. DataBase. Esempi di database

Informatica per le discipline umanistiche 2 lezione 10

Basi di Dati. S Q L Lezione 5

Sviluppata da: Lo Russo - Porcelli Pag. 1 di 6 6FRSR utilizzare il DBMS Postgresql per imparare il linguaggio SQL.

MySQL Database Management System

Laboratorio di Basi di Dati e Web

SQL Server Integration Services. SQL Server 2005: ETL - 1. Integration Services Project

Interrogazioni nidificate, commenti

Archivi e database. Prof. Michele Batocchi A.S. 2013/2014

TEORIA sulle BASI DI DATI

Automatizzare i compiti ripetitivi. I file batch. File batch (1) File batch (2) Visualizzazione (2) Visualizzazione

Транскрипт:

Oracle PLSQL Motivazioni Supponiamo che nella gestione del database Azienda ci venga chiesto di apportare le modifiche necessarie a far sì che ad ogni impiegato possa essere assegnato, alla fine di ogni anno, un bonus da calcolarsi così: Per ciascun progetto a cui un impiegato partecipa, l impiegato riceve un bonus pari all 1% del budget di progetto Gli impiegati che partecipano a più progetti hanno un bonus pari alla somma dei bonus relativi a ciascun progetto Ogni volta che vengono portate a termine le operazioni per il calcolo del bonus, si vuole anche conoscere la somma totale dei bonus assegnati agli impiegati 2 1

Motivazioni Le operazioni richieste, difficilmente possono essere eseguite attraverso un unico comando SQL Inizializzare a zero il valore del bonus di ciascun impiegato Conoscere il numero di progetti a cui partecipa ciascun impiegato Incrementare il valore del bonus sulla base del budget di progetto Tenere traccia di tutti gli incrementi effettuati per calcolare la somma di tutti I bonus È dunque conveniente il ricorso a più comandi SQL per elaborare in cascata i dati dell archivio, possibilmente facendo uso di opportune variabili di appoggio Tutto questo richiede una estensione delle funzionalità base di SQL!!! 3 PLSQL Senza PLSQL, le istruzioni SQL vengono trasmesse e processate una alla volta Programmi che prevedono molte istruzioni SQL devono effettuare molteplici chiamate al DBMS, con ricadute su traffico di rete e tempi complessivi di elaborazione Con PLSQL, un intero blocco di istruzioni può essere inviato al DBMS L elaborazione dei risultati intermedi non deve essere trasmessa all applicazione che riceve solo il risultato finale dell elaborazione Con PLSQL si possono anche definire stored procedures che sono compilate e memorizzate in forma eseguibile per ridurre i tempi di esecuzione Con le stored procedures il traffico di rete è ulteriorimente ridotto dato che si passano solo i parametri, non l intero codice. Inoltre le stored procedures possono essere condivise tra utenti diversi riducendo i requisiti complessivi di memoria 4 2

Struttura Ogni programma PLSQL è costituito da blocchi logici (in cascata o nidificati) ciascuno dei quali raggruppa tre sezioni: dichiarativa (DECLARE) istruzioni d esecuzione (END) gestione eccezioni (EXCEPTION) In un blocco, possono essere dichiarate costanti e variabili. Le variabili possono essere utilizzate per memorizzare i risultati di una query Un blocco PLSQL può contenere istruzioni SQL, strutture di controllo del flusso d esecuzione (for-loop, while-loop, if-then-else, casewhen), manipolazione delle eccezioni (controllo errori), e chiamate ad altri blocchi PLSQL I blocchi PLSQL che specificano procedure e funzioni possono essere raggruppati in packages 5 Struttura Un altra importante caratteristica di PLSQL è che offre un meccanismo per processare i risultati delle query in un modo orientato alle tuple una tupla alla volta A questo scopo, vengono utilizzati i cursori Un cursore è fondamentalmente un puntatore al risultato di una query ed è impiegato per leggere i valori degli attributi delle tuple selezionate, inserendoli in variabili Un cursore è tipicamente usato in combinazione con un costrutto loop per elaborare, riga per riga, i risultati di una query 6 3

Dichiarazioni Costanti, variabili, cursori ed eccezioni usate in un blocco PLSQL devono essere dichiarati nella sezione di dichiarazione di quel blocco La dichiarazione di variabili e costanti ha la seguente sintassi: <nome variabile> [costant] <tipo di dati> [not null] [:= <espressione>]; DECLARE wages NUMBER; --Inizializzazione con null hours_worked CONSTANT NUMBER := 40; hourly_salary NUMBER := 22.50; bonus NUMBER := 150; country VARCHAR2(128); --Inizializzazione con null 7 Dichiarazioni PLSQL supporta la dichiarazione ancorata del tipo di dato di una variabile Si può richiedere che la variabile abbia lo stesso tipo di una particolare colonna di una tabella IMPIEGATO.Matricola%TYPE Oppure abbia un tipo in grado di memorizzare una tupla completa di una determinata tabella (o risultato di query) DIPARTIMENTO%ROWTYPE 8 4

Dichiarazioni La dichiarazione di un cursore specifica un insieme di tuple (come risultato di una query) in modo che le tuple possano essere processate individualmente, una alla volta, usando l istruzione fetch La dichiarazione di un cursore ha la seguente sintassi: cursor <nome cursore> [(<lista parametri>)] is <istruzione select>; Se le tuple selezionate dal cursore devono essere modificate all interno del blocco PLSQL, deve essere aggiunta la clausola for update [(<colonna(e)>)] alla fine della dichiarazione del cursore In questo caso le tuple vengono bloccate e gli altri utenti non vi possono accedere finché non è stato eseguito un comando commit 9 Dichiarazioni Le eccezioni vengono usate per processare errori e avvisi che si incontrano durante l esecuzione delle istruzioni PLSQL Alcune eccezioni sono definite internamente: ZERO_DIVIDE (divisione per 0) Altre eccezioni possono essere specificate dall utente alla fine di un blocco PLSQL Le eccezioni definite dall utente devono essere dichiarate usando la sintassi <nome eccezione> exception 10 5

Variabili Ci sono tre modi per assegnare un valore ad una variabile: Attraverso l operatore := seguito dal valore DECLARE wages NUMBER; --Inizializzazione con null hours_worked CONSTANT NUMBER := 40; hourly_salary NUMBER := 22.50; bonus NUMBER := 150; country VARCHAR2(128); --Inizializzazione con null wages := (hours_worked * hourly_salary) + bonus; country := 'France'; country := UPPER('Canada'); 11 Variabili Ci sono tre modi per assegnare un valore ad una variabile: Attraverso l operatore := seguito dal valore Attraverso il costrutto SELECT INTO In questo caso bisogna che l istruzione select recuperi almeno una tupla, altrimenti verrà notificato un errore! Se l istruzione recupera più di una tupla, allora deve essere utilizzato un cursore. DECLARE employee_rec EMP%ROWTYPE; max_sal EMP.SAL%TYPE; select EMPNO, ENAME, JOB, MGR, SAL, COMM, HIREDATE, DEPTNO into employee_rec from EMP where EMPNO = 5698; select max(sal) into max_sal from EMP; 12 6

Variabili Ci sono tre modi per assegnare un valore ad una variabile: Attraverso l operatore := seguito dal valore Attraverso il costrutto SELECT INTO Attraverso passaggio di parametri ad una subroutine con i costrutti IN, OUT ed IN OUT DECLARE new_sal NUMBER(8,2); emp_id NUMBER(6) := 126; PROCEDURE adjust_salary(emp_id NUMBER, sal IN OUT NUMBER) IS emp_job VARCHAR2(10); avg_sal NUMBER(8,2); SELECT AVG(salary) INTO new_sal FROM employees; adjust_salary(emp_id, new_sal); -- assigns a new value to new_sal 13 Costrutti per il controllo di flusso Costrutti per il controllo condizionale: IF-THEN-ELSE CASE-WHEN Costrutti per il controllo di iterazione: LOOP FOR-LOOP WHILE-LOOP Costrutti per l interruzione di flusso: GOTO 14 7

Costrutti per il controllo di flusso Per il controllo condizionale, PLSQL offre costrutti if-then-else nella forma: if <condizione> then <sequenza di istruzioni> [elsif] <condizione> then <sequenza di istruzioni> [else] <sequenza di istruzioni> end if; 15 Cursori I cursori sono necessari per gestire i dati recuperati da istruzioni di select Fanno eccezione le query che restituiscono un solo dato o una singola tupla Prima che un cursore (già dichiarato nella sezione DECLARE) possa essere usato, deve essere aperto utilizzando l istruzione open: open <nome cursore> [(<lista di parametri>)]; L istruzione select associata viene quindi processata e il cursore punta alla prima tupla restituita dalla select 16 8

Cursori Le tuple selezionate possono essere processate una alla volta utilizzando il comando fetch fetch <nome cursore> [(<lista di parametri>)]; Tipicamente la lista di parametri specifica alcune variabili dove memorizzare i valori dalla tupla corrente del cursore le variabili devono avere lo stesso tipo di dati dei risultati della select Dopo un comando fetch, il cursore avanza alla successiva tupla nell insieme del risultato dell istruzione select Dopo che tutte le tuple sono state processate, si utilizza il comando close per chiudere e disabilitare il cursore close <nome cursore>; 17 Cursori L avanzamento del cursore all interno del risultato può essere gestito attraverso un loop semplice: DECLARE cursor emp_cur is select * from EMP; emp_rec EMP%ROWTYPE; emp_sal EMP.SAL%TYPE; open emp_cur; loop fetch emp_cur into emp_rec; exit when emp_cur%notfound; emp_sal := emp_rec.sal; close emp_cur; 18 9

Cursori L avanzamento del cursore all interno del risultato può essere semplificato con un loop for: [<< <nome etichetta> >>] for <nome record> in <nome cursore> [(lista di parametri>)] loop <sequenza di istruzioni> Un record utilizzabile per memorizzare una tupla recuperata da un cursore viene implicitamente dichiarato Inoltre, questo loop esegue implicitamente una fetch ad ogni iterazione, una open prima dell ingresso nel loop e una close dopo che il loop è terminato Se ad un iterazione nessuna tupla viene recuperata, il loop viene automaticamente terminato senza un exit 19 Cursori [<< <nome etichetta> >>] for <nome record> in <nome cursore> [(lista di parametri>)] loop <sequenza di istruzioni> In un loop for è anche possibile specificare una query al posto di <nome cursore> : for <nome record> in (<istruzione select>) loop <sequenza di istruzioni> DECLARE sal_rec EMP.SAL%TYPE; for sal_rec in (select SAL + COMM total from EMP) loop ; 20 10

Esempio Il seguente codice aumenta del 5% lo stipendio degli impiegati che hanno KING come loro responsabile Si usa il costrutto cursor-for-update che integra la funzione di update all interno del cursore DECLARE manager EMP.MGR%TYPE; cursor emp_cur (mgr_no number) is select SAL from EMP where MGR = mgr_no for update of SAL; select EMPNO into manager from EMP where ENAME = 'KING'; for emp_rec in emp_cur(manager) loop update EMP set SAL = emp_rec.sal*1.05 where current of emp_cur; commit; 21 Esercizio Dopo aver abilitato l output sul terminale SQLPLUS (set serveroutput on) definire ed eseguire una procedura che stampi matricola, cognome e stipendio di ciascun impiegato DECLARE emp_mat IMPIEGATO.MATRICOLA%TYPE; emp_cog IMPIEGATO.COGNOME%TYPE; emp_sti IMPIEGATO.STIPENDIO%TYPE; for emp_rec in (select * from IMPIEGATO) loop DBMS_OUTPUT.PUT_LINE('Matricola: ' emp_rec.matricola ' Cognome: ' emp_rec.cognome ' Stipendio: ' TO_CHAR(emp_rec.stipendio)); for emp_rec in (select * from IMPIEGATO) loop emp_mat := emp_rec.matricola; emp_cog := emp_rec.cognome; emp_sti := emp_rec.stipendio; DBMS_OUTPUT.PUT_LINE ('Matricola: ' emp_mat ' Cognome: ' emp_cog ' Stipendio: ' TO_CHAR(emp_sti)); 22 11

DECLARE cursor emp_cur is select * from IMPIEGATO; emp_rec IMPIEGATO%ROWTYPE; Esercizio emp_mat IMPIEGATO.MATRICOLA%TYPE; emp_cog IMPIEGATO.COGNOME%TYPE; emp_sti IMPIEGATO.STIPENDIO%TYPE; open emp_cur; loop fetch emp_cur into emp_rec; exit when emp_cur%notfound; emp_mat := emp_rec.matricola; emp_cog := emp_rec.cognome; emp_sti := emp_rec.stipendio; DBMS_OUTPUT.PUT_LINE ('Matricola: ' emp_mat ' Cognome: ' emp_cog ' Stipendio: ' TO_CHAR(emp_sti)); close emp_cur; DECLARE cursor emp_cur is select * from IMPIEGATO; emp_mat IMPIEGATO.MATRICOLA%TYPE; emp_cog IMPIEGATO.COGNOME%TYPE; emp_sti IMPIEGATO.STIPENDIO%TYPE; for emp_rec in emp_cur loop emp_mat := emp_rec.matricola; emp_cog := emp_rec.cognome; emp_sti := emp_rec.stipendio; DBMS_OUTPUT.PUT_LINE ('Matricola: ' emp_mat ' Cognome: ' emp_cog ' Stipendio: ' TO_CHAR(emp_sti)); 23 Esercizio Con riferimento alla base dati impiegatodipartimento-progetto-pp, definire una procedura che individui i responsabili di progetto che guadagnano meno degli impiegati che supervisionano ed aumentarne lo stipendio in modo che guadagnino almeno quanto gli impiegati che supervisionano: Per ogni supervisore calcolare lo stipendio massimo dei suoi supervisionati Se maggiore del proprio stipendio aggiornare il proprio stipendio a tale valore 24 12

Esercizio Per ogni supervisore calcolare lo stipendio massimo dei suoi supervisionati: select s.matricola, s.stipendio, max(i.stipendio) from impiegato s, progetto p, pp, impiegato i where s.matricola=p.responsabile AND p.codice=pp.progetto AND pp.impiegato=i.matricola group by s.matricola, s.stipendio 25 Esercizio Nota la matricola del supervisore aggiornarne il valore di stipendio: update impiegato set stipendio = new_stipendio where matricola=mat_leader 26 13

Esercizio DECLARE cursor emp_cur is select s.matricola, s.stipendio, max(i.stipendio) as max_stip from impiegato s, progetto p, pp, impiegato i where s.matricola=p.responsabile AND p.codice=pp.progetto AND pp.impiegato=i.matricola group by s.matricola, s.stipendio; emp_mat IMPIEGATO.MATRICOLA%TYPE; emp_sti_s IMPIEGATO.STIPENDIO%TYPE; emp_sti_i IMPIEGATO.STIPENDIO%TYPE; for emp_rec in emp_cur loop emp_mat := emp_rec.matricola; emp_sti_s := emp_rec.stipendio; emp_sti_i := emp_rec.max_stip; if emp_sti_s < emp_sti_i then update impiegato set stipendio = emp_sti_i where matricola=emp_mat; commit; end if; 27 Stored procedures Il comando CREATE PROCEDURE (o CREATE FUNCTION) consente di definire procedure (o funzioni) che vengono memorizzate nel server e richiamate attraverso il comando EXECUTE Procedure e funzioni possono ricevere parametri di ingresso che vengono passati alla loro chiamata Le funzioni possono anche restituire dei valori al termine della loro esecuzione 28 14

Stored procedures Sintassi per la definizione di una procedura create [or replace] procedure <nome procedura> [(<lista di parametri>)] is <dichiarazione> begin <sequenza di istruzioni> [exception <routine di gestione dell eccezione>] end [<nome procedura>]; e di una funzione: create [or replace] function <nome funzione> [(<lista di parametri>)] return <tipo di dati> is <dichiarazione> begin 29 Stored procedures Una volta create, procedure e funzioni possono essere cancellate attraverso i comandi drop procedure <nome procedura> drop function <nome funzione> 30 15

Stored procedures La specifica dei parametri prevede la seguente sintassi: <nome parametro> [IN OUT IN OUT] <tipo di dato> [{:= DEFAULT} <espressione>] La clausola opzionale IN, OUT, e IN OUT specifica il modo nel quale il parametro è utilizzato (se omessa il parametro è considerato IN) IN significa che il parametro è accessibile in lettura ma non in scrittura OUT significa che il parametro è accessibile in scrittura ma non in lettura IN OUT permette di accedere al parametro sia in lettura che scrittura 31 Stored procedures Procedura che aumenta lo stipendio degli affiliati ad un dipartimento di una percentuale variabile Una volta creata, la procedura può essere chiamata con execute raise_salary('d002', 0.3) dal terminale sqlplus Se la procedura viene chiamata dall interno di un blocco PLSQL, la parola chiave execute viene omessa create procedure raise_salary(dno dipartimento.codice%type, percentage number DEFAULT 0.5) is cursor emp_cur (dept_no dipartimento.codice%type) is select STIPENDIO from IMPIEGATO where DIPARTIMENTO = dept_no for update of STIPENDIO; empsal number(8); begin for emp_rec in emp_cur(dno) loop update IMPIEGATO set STIPENDIO = emp_rec.stipendio*((100+percentage)100) where current of emp_cur; commit; 32 end raise_salary; 16

Stored procedures oppure con begin raise_salary('d002', 0.3); end; dall interno di un blocco PLSQL Questa è la modalità da adottare per eseguire la procedura dal pannello SQL commands dell interfaccia web create procedure raise_salary(dno dipartimento.codice%type, percentage number DEFAULT 0.5) is cursor emp_cur (dept_no dipartimento.codice%type) is select STIPENDIO from IMPIEGATO where DIPARTIMENTO = dept_no for update of STIPENDIO; empsal number(8); begin for emp_rec in emp_cur(dno) loop update IMPIEGATO set STIPENDIO = emp_rec.stipendio*((100+percentage)100) where current of emp_cur; commit; end raise_salary; 33 Stored procedures Da notare che la procedura poteva essere scritta molto più semplicemente senza ricorrere al costrutto del cursor for update create procedure quick_raise_salary(dno dipartimento.codice%type, percentage number DEFAULT 0.5) is begin update IMPIEGATO set STIPENDIO = STIPENDIO*((100+percentage)100) where DIPARTIMENTO=dno; end quick_raise_salary; Il costrutto del cursor for update è tuttavia necessario quando l elaborazione richiede di operare su una riga alla volta di una tabella 34 17

Stored procedures Per poter richiamare una funzione da una shell di SQL*Plus, è necessario prima definire una variabile alla quale assegnare il risultato della funzione In SQL*Plus, una variabile può essere definita utilizzando il comando variable <nome variabile> <tipo di dati>; variable salary number. La funziona sopra può quindi essere chiamata usando il comando execute :salary := get_dept_salary(20); Da notare i due punti che devono essere messi davanti alla variabile salary 35 Stored procedures La seguente funzione incrementa gli stipendi e restituisce la somma degli incrementi effettuati create or replace function raise_salary(dno varchar2, percentage number DEFAULT 0.5) return number is delta_sal number; cursor emp_cur (dept_no varchar2) is select STIPENDIO from IMPIEGATO where DIPARTIMENTO = dept_no for update of STIPENDIO; empsal IMPIEGATO.STIPENDIO%TYPE; begin delta_sal := 0.0; open emp_cur(dno); loop fetch emp_cur into empsal; exit when emp_cur%notfound; if empsal IS NOT NULL then delta_sal := delta_sal + empsal*(percentage100); update IMPIEGATO set STIPENDIO = empsal*((100+percentage)100) where current of emp_cur; end if; close emp_cur; commit; return delta_sal; 36 end raise_salary; 18

Stored procedures Il funzionamento della funzione può essere verificato eseguendo dalla shell SQLPLUS i seguenti comandi: declare dato number(12,2); begin dato := raise_salary('d001'); dbms_output.put_line(to_char(dato)); end; 37 Esercizio Aggiungere alla tabella impiegato un campo bonus (number) Definire una funzione che imposti il valore di bonus in base al seguente criterio: Per ciascun progetto a cui un impiegato partecipa, l impiegato riceve un bonus pari all 1% del budget di progetto Gli impiegati che partecipano a più progetti hanno un bonus pari alla somma dei bonus relativi a ciascun progetto Ogni volta che viene chiamata la funzione restituisce la somma dei bonus assegnati agli impiegati 38 19

Soluzione alter table IMPIEGATO add BONUS number default 0.0; create or replace function calcola_bonus return IMPIEGATO.BONUS%TYPE is total_bonus IMPIEGATO.BONUS%TYPE; current_bonus IMPIEGATO.BONUS%TYPE; cursor emp_cur is select * from IMPIEGATO for update of BONUS; cursor proj_budget (emp_mat IMPIEGATO.MATRICOLA%TYPE) is select p.budget from progetto p, pp where IMPIEGATO=emp_mat AND PROGETTO=CODICE; begin total_bonus := 0.0; for emp_rec in emp_cur loop current_bonus := 0.0; for cur_bud in proj_budget(emp_rec.matricola) loop current_bonus := current_bonus + cur_bud.budget*0.01; update IMPIEGATO set BONUS = current_bonus where current of emp_cur; total_bonus := total_bonus + current_bonus; commit; return total_bonus; end calcola_bonus; 39 Soluzione declare bingo impiegato.bonus%type; begin bingo := calcola_bonus; DBMS_OUTPUT.PUT_LINE(to_char(bingo)); end; 40 20