Esercizi riassuntivi PL/SQL
1) Sia dato il seguente schema relazionale che modella parte del database del SI di un ospedale:
PAZIENTI(CF,Nome,Cognome,Sesso,DataN)
PRESTAZIONI(Cod Nome,Costo)
RICOVERI(Paziente:PAZIENTI,DataInizio,DataFine)
EROGAZIONI(Paziente:Paziente:RICOVERI,DataRicovero:DataInizio:RICOVERI,
Prestazione:PRESTAZIONI)
a) Si definisca la base di dati su ORACLE
b) Si scriva la stored procedure Costi che, dato in input un intervallo temporale, calcoli il
ricovero più costoso come quello che massimizza la seguente funzione di costo
SE Durata < 7 gg --> F = 20 + Sum(Costo) - Durata*2
SE Durata >= 7 gg --> F = 15 + Sum(Costo) - Durata*1.5
In output si forniscano tutti i dati ad esso relativi (dati paziente, dati ricovero, e dati erogazioni).
La Durata si considera espressa in giorni. Attenzione ad escludere dal computo i ricoveri non
ancora conclusi.
2) Sia dato il seguente schema relazionale che modella parte del database del DB di un call center:
CLIENTI(IdCliente, Nome, Cognome, DataN, Telefono, TipoContratto)
OPERATORI(IdOp, Nome, Cognome, DataN, Livello)
PROBLEMI(Codice, Descrizione, Classe, Difficoltà)
CHIAMATE(IdChiamata, Cliente:CLIENTI, Operatore:OPERATORI, Problema:PROBLEMI,
DataApertura, Risultato)
OPERAZIONI(Chiamata:CHIAMATE, DataOra, Durata, Descrizione)
a) Si definisca la base di dati su ORACLE
b) Si scriva la stored procedure RatingOperatori(v_data date) che stila una classifica
delle performance degli operatori a partire v_data e restituisce in output quelli con valutazione
negativa. La valutazione è calcolata in base al seguente algoritmo
Valutazione= (VPos-Vneg)/( VPos+Vneg)
 VPos è la quantità di tempo speso da ogni operatore per gestire chiamate conclusesi
positivamente (Risultato=1) e pesate per il livello di difficoltà del problema relativo
(Difficoltà ]0,..1]).
 VNeg è uguale a VPos ma per le chiamate conclusesi negativamente (Risultato = -1)
Le chiamata non ancora conclusesi hanno il campo Risultato = 0 e non devono essere
considerate nel conteggio.
3) Sia dato il seguente schema relazionale che modella la porzione del database dell’ARPA relativo
al monitoraggio dell’inquinamento:
REGIONI(Nome, NumAbitanti)
CITTA(Nome, Regione:REGIONI, NumAbitanti, Distretto:DISTRETTI)
PARAMETRI(Citta:CITTA, Regione:CITTA, Parametro, TipoParametro, Descrizione, Valore)
DISTRETTI(Nome, Descrizione)
OUTPUT(Citta:CITTA, Regione:CITTA, Valore)
a) Si definisca la base di dati su ORACLE
b) Si scriva la procedura Vivibile(VRegione) che inserisca in OUTPUT la graduatoria delle 5
città della regione passata in input che massimizzano il principio di vivibilità così definito: (1) si
individuino le 10 città della regione che minimizzano la media dei parametri di tipo
“Inquinamento” (2) tra queste si costruisca la graduatoria in base alla formula
DimAreeVerdi 
NumCentriCulturali 
1 

NumAbitanti 
10

dove DimAreeVerdi, NumCentriCulturali sono istanze dell’attributo Parametro.
Soluzioni esercizi riassuntivi PL/SQL
Esercizio 1
create table PAZIENTI (
P_CF varchar2(16),
P_NOME varchar2(20),
P_COGNOME varchar2(20),
P_SESSO int,
P_DATAN date,
primary key (P_CF));
create table PRESTAZIONI(
S_COD int,
S_NOME varchar2(50),
S_COSTO float,
primary key (S_COD));
create table RICOVERI (
R_PAZIENTE varchar2(16),
R_DATAI date,
R_DATAF date,
primary key (R_PAZIENTE,R_DATAI),
foreign key (R_PAZIENTE) references PAZIENTI (P_CF));
create table EROGAZIONI (
E_PAZIENTE varchar2(16),
E_DATARIC date,
E_PRESTAZIONE int,
primary key (E_PAZIENTE,E_DATARIC,E_PRESTAZIONE),
foreign key (E_PAZIENTE,E_DATARIC) references RICOVERI(R_PAZIENTE,R_DATAI),
foreign key (E_PRESTAZIONE) references PRESTAZIONI (S_COD));
create or replace procedure Costi(v_DataI date, v_DataF date) IS
CURSOR ricoveri_cursor IS
select R_PAZIENTE,R_DATAI,R_DATAF,sum(S_COSTO)
from RICOVERI,EROGAZIONI,PRESTAZIONI
where R_PAZIENTE=E_PAZIENTE and R_DATAI=E_DATARIC and R_DATAI BETWEEN v_DataI
and v_DataF and R_DATAF BETWEEN v_DataI and v_DataF
and S_COD=E_PRESTAZIONE
group by R_PAZIENTE,R_DATAI,R_DATAF;
v_costo float;
v_durata INT;
v_DurataMax INT;
v_max float :=0;
v_Data date;
v_CF PAZIENTI.P_CF%TYPE;
c_CF PAZIENTI.P_CF%TYPE;
c_DataI RICOVERI.R_DATAI%TYPE;
c_DataF RICOVERI.R_DATAF%TYPE;
c_Costo PRESTAZIONI.S_COSTO%TYPE;
r_paziente PAZIENTI%rowtype;
BEGIN
open ricoveri_cursor;
loop
fetch ricoveri_cursor into c_CF,c_DataI,c_DataF,c_Costo;
exit when ricoveri_cursor%NOTFOUND;
v_Durata:=c_DataF-C_DataI;
if (v_Durata<7) then
v_costo:=20 + c_Costo -2*(v_Durata);
else
v_costo:=15 + c_Costo -1.5*(v_Durata);
end if;
if (v_costo>v_max) then
v_max:=v_costo;
v_DurataMax:=v_Durata;
v_CF:=c_CF;
v_Data:=c_DataI;
end if;
end loop;
close ricoveri_cursor;
DBMS_OUTPUT.PUT_LINE('Il ricovero più costoso è durato ' || v_DurataMax || '
giorni, il costo é ' || v_max || ' in data ' || v_Data);
select * INTO r_paziente
from PAZIENTI
where P_CF=c_CF;
DBMS_OUTPUT.PUT_LINE('Il ricovero è relativo a ' || r_paziente.P_NOME || ' ' ||
r_paziente.P_COGNOME);
END Costi;
Esercizio 2
create table CLIENTI (
C_ID int,
C_NOME varchar2(20),
C_COGNOME varchar2(20),
C_DATAN date,
C_TELEFONO varchar2(50),
C_TIPOCONTR varchar2(20),
primary key (C_ID));
create table OPERATORI (
O_ID int,
O_NOME varchar2(20),
C_COGNOME varchar2(20),
O_DATAN date,
O_LIVELLO int,
primary key (O_ID));
create table PROBLEMI (
P_COD varchar2(16),
P_DESCRIZIONE varchar2(50),
P_CLASSE varchar2(20),
P_DIFF float,
primary key (P_COD));
create table CHIAMATE(
C_ID int,
C_CLIENTE int,
C_OPERATORE int,
C_PROBLEMA varchar2(16),
C_APERTURA date,
C_RISULTATO int,
primary key (C_ID),
foreign key (C_CLIENTE) references CLIENTI(C_ID),
foreign key (C_OPERATORE) references OPERATORI(O_ID),
foreign key (C_PROBLEMA) references PROBLEMI(P_COD));
create table OPERAZIONI(
R_CHIAMATA int,
R_DATAORA date,
R_DURATA int,
R_DESCRIZIONE varchar2(50),
primary key (R_CHIAMATA,R_DATAORA),
foreign key (R_CHIAMATA) references CHIAMATE(C_ID));
create or replace procedure RatingOperatori(v_Data date) IS
CURSOR cursor_operatori IS
select distinct C_OPERATORE
from
CHIAMATE
where C_APERTURA>=v_Data and C_RISULTATO!=0;
c_OP CHIAMATE.C_OPERATORE%TYPE;
v_pos float;
v_neg float;
v_valutazione float;
BEGIN
open cursor_operatori;
loop
fetch cursor_operatori into c_OP;
exit when cursor_operatori%NOTFOUND;
v_pos :=0;
select sum(R_DURATA*P_DIFF) into v_pos
from
CHIAMATE, OPERAZIONI,PROBLEMI
where C_ID=R_CHIAMATA and C_PROBLEMA=P_COD and C_RISULTATO=1
and C_OPERATORE=c_OP and C_APERTURA>=v_Data;
v_neg :=0;
select sum(R_DURATA*P_DIFF) into v_neg
from
CHIAMATE, OPERAZIONI,PROBLEMI
where C_ID=R_CHIAMATA and C_PROBLEMA=P_COD and C_RISULTATO=-1
and C_OPERATORE=c_OP and C_APERTURA>=v_Data;
if (v_Pos+V_Neg<>0) then
v_Valutazione:=(v_Pos-V_Neg)/(v_Pos+V_Neg);
else
v_Valutazione:=0;
end if;
if (v_Valutazione<0) then
DBMS_OUTPUT.PUT_LINE('L''operatore ' || c_OP
|| 'ha ottenuto una negativa pari a:' || v_Valutazione);
end if;
end loop;
close cursor_operatori;
END
RatingOperatori;