You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
RISOLUZIONE APPELLI<br />
DI<br />
SISTEMI INFORMATIVI<br />
a cura di<br />
E. Di Sciascio ed E. Tinelli
CONSIDERAZIONI PRELIMINARI ................................................................................................. 3<br />
APPELLO 28 LUGLIO 2006 ........................................................................................................... 4<br />
<strong>Esercizi</strong>o a ................................................................................................................................. 4<br />
<strong>Esercizi</strong>o b ................................................................................................................................. 6<br />
<strong>Esercizi</strong>o c ................................................................................................................................. 7<br />
<strong>Esercizi</strong>o d ................................................................................................................................. 8<br />
APPELLO 17 FEBBRAIO 2006 ...................................................................................................... 9<br />
<strong>Esercizi</strong>o a ................................................................................................................................. 9<br />
<strong>Esercizi</strong>o b ............................................................................................................................... 11<br />
<strong>Esercizi</strong>o c ............................................................................................................................... 12<br />
<strong>Esercizi</strong>o d ............................................................................................................................... 13<br />
APPELLO 12 FEBBRAIO 2008................................................................................................... 14<br />
<strong>Esercizi</strong>o a............................................................................................................................... 14<br />
<strong>Esercizi</strong>o b............................................................................................................................... 16<br />
<strong>Esercizi</strong>o c ............................................................................................................................... 17<br />
<strong>Esercizi</strong>o d............................................................................................................................... 18<br />
Esempi di Normalizzazione........................................................................................................... 19<br />
1) Appello 7 Aprile 2006 .......................................................................................................... 19<br />
2) Appello 23 Giugno 2006...................................................................................................... 21<br />
3) Appello 28 Settembre 2006................................................................................................. 22<br />
ESEMPI di query SQL.................................................................................................................. 23<br />
1) Appello 21 Novembre 2006................................................................................................. 23<br />
2) Appello 28 Settembre 2006................................................................................................. 24<br />
3) Appello 24 Settembre 2005 ed Esempi vari ........................................................................ 25
CONSIDERAZIONI PRELIMINARI<br />
1. Si osservi che generalmente non esiste una soluzione unica per la risoluzione di un appello.<br />
Pertanto le risoluzioni qui proposte rappresentano esclusivamente un esempio di buone<br />
pratiche, mA non escludono altre risoluzioni formalmente e sostanzialmente corrette. In questo<br />
eserciziario, pertanto, si illustra una delle possibili soluzioni.<br />
2. L’esercizio b va svolto scrivendo le CREATE TABLE corrispondenti a ciascuna relazione del<br />
modello E-R dell’esercizio a. Per semplicità, in questo eserciziario, riportiamo il risultato del<br />
mapping in forma tabellare ed esplicitiamo in SQL solamente le relazioni più complesse.<br />
3. Quando nell’esercizio a si individua un attributo calcolato (o attributo derivato) è possibile<br />
(ma non necessario) scrivere nell’esercizio b, senza ricorrere all’uso dei trigger, la query SQL<br />
che servirebbe per calcolare il suddetto attributo.<br />
4. Per business rules si intendono quelle regole che è necessario verificare e che non possono<br />
essere espresse nel modello E-R. Generalmente tali regole possono essere espresse in SQL<br />
nell’esercizio b mediante check , assertion e trigger.<br />
5. L’esercizio c può essere svolto secondo i seguenti 2 approcci:<br />
- trovare prima la chiave della tabella(anche procedendo per tentativi) e quindi le eventuali<br />
dipendenze piene dalla chiave, le dipendenze parziali e/o transitive dalla chiave;<br />
- trovare tutte le dipendenze funzionali in base alla semantica dei dati ed alle ipotesi del<br />
problema e poi individuare la chiave della tabella.<br />
In questo eserciziario si utilizza il secondo approccio.
APPELLO 28 LUGLIO 2006<br />
<strong>Esercizi</strong>o a<br />
Si progetti uno schema concettuale Entità-Relazioni per lo scenario più sotto descritto.<br />
Una base di dati deve essere utilizzata per gestire gli ordini di un’azienda che produce PC ed<br />
organizzarne la produzione.<br />
Bisogna tener traccia dei dettaglianti che effettuano gli ordini dei PC e dei fornitori che<br />
forniscono i componenti necessari all’azienda per assemblare i PC. Sia i dettaglianti che i fornitori<br />
sono caratterizzati dai seguenti dati: partita iva, ragione sociale, indirizzo, telefono ed e-mail.<br />
Sia i PC che i loro componenti sono caratterizzati da un codice univoco, un nome ed un prezzo.<br />
Inoltre, per i componenti è necessario memorizzare il fornitore di riferimento, mentre per i PC il<br />
numero di pezzi (minore o uguale a 30) ed i componenti che li costituiscono. Bisogna verificare<br />
anche che il numero di pezzi sia inferiore a 20 se il prezzo del PC è inferiore a 1000 euro.<br />
È necessario, infine, tenere traccia dei seguenti eventi:<br />
- gli ordini dei PC da parte dei dettaglianti caratterizzati dalla data ed ora dell’ordine, dalla data di<br />
consegna pattuita, dal tipo di pagamento (anticipato, alla consegna, a 30 gg) e dai PC ordinati con<br />
le relative quantità;<br />
- il processo di assemblaggio di un PC caratterizzato dalla data ed ora di inizio del processo,<br />
dall’ora di fine e dal dipendente che si occupa dell’assemblaggio.<br />
Ciascun dipendente è caratterizzato dai seguenti dati: codice fiscale, nome, cognome, data di<br />
nascita e di assunzione.<br />
Indicare le cardinalità delle relazioni e un identificatore per ciascuna entità.<br />
Osservazioni:<br />
1)Le due entità fornitore e dettagliante sono caratterizzate dagli stessi dati ma non è necessario<br />
modellare una gerarchia costituita nel seguente modo:<br />
- entità padre: azienda<br />
- entità figlie: fornitore e dettagliante.<br />
Il motivo è il seguente: le altre entità del modello fanno riferimento all’entità fornitore oppure<br />
all’entità dettagliante ma mai ad una generica azienda, pertanto la gerarchia doveva risolversi<br />
portando i figli nel padre. Il risultato è quindi quello di avere nel modello E-R due entità distinte<br />
fornitore e dettagliante ciascuna con i sui attributi e le sue relazioni.<br />
2) Le due entità PC e componente sono caratterizzate da alcuni dati in comune, in particolare dalla<br />
chiave codice, ma non è necessario modellare una gerarchia costituita nel seguente modo:<br />
- entità padre: prodotto<br />
- entità figlie: PC e componente.<br />
Considerando che un pc ed un componente non sono “materialmente” la stessa cosa (difatti un pc è<br />
costituito dall’insieme dei componenti) e che le altre entità del modello fanno sempre riferimento<br />
all’entità PC oppure all’entità componente ma mai ad un generico prodotto, una eventuale gerarchia<br />
doveva risolversi portando i figli nel padre. Anche in questo caso il risultato è quello di avere nel<br />
modello E-R due entità distinte PC e componente ciascuna con i sui attributi e le sue relazioni.
Business rules:<br />
1. il numero di pezzi deve essere minore o uguale a 30;<br />
2. il numero di pezzi deve essere inferiore a 20 quando il prezzo del PC è inferiore a 1000<br />
euro;<br />
3. il tipo di pagamento può assumere i seguenti 3 valori: ‘anticipato‘, ‘alla consegna’, ‘a 30<br />
gg’.
<strong>Esercizi</strong>o b<br />
Si definiscano le relazioni (tabelle) risultanti in SQL, avendo cura di esplicitare i vincoli di integrità.<br />
DETTAGLIANTE ( PIVA, ragione_sociale, indirizzo, Tel, e-mail )<br />
FORNITORE ( PIVA, ragione_sociale, indirizzo, Tel, e-mail )<br />
PC ( codice, nome, prezzo, N_pezzi )<br />
COMPONENTE ( codice, nome, prezzo, PIVA_fornitore )<br />
PC_componente ( codicePC, codiceComp )<br />
ORDINE ( data, ora, PIVA_dett, data_consegna, tipo_pagamento )<br />
ORDINE_PC ( data, ora, PIVA_dett, codicePC, quantità )<br />
DIPENDENTE ( CF, nome, cognome, data_nascita, data_assunzione )<br />
ASSEMBLAGGIO ( data_in, ora_in, CF_dipendente, codicePC, ora_fine )<br />
CREATE TABLE PC<br />
( codice char (8) primary key,<br />
nome varchar(30) NOT NULL,<br />
prezzo numeric (7,2) NOT NULL,<br />
N_pezzi int check ( N_pezzi < = 30 ),<br />
check ( N_pezzi >=20 OR (N_pezzi
<strong>Esercizi</strong>o c<br />
Si vuole realizzare un database relativo alla organizzazione dei provini delle Agenzie di casting<br />
italiane. E’ stata a tal fine costruita, da un inesperto progettista, una unica tabella descritta dai<br />
seguenti attributi:<br />
(PIVA_agenzia, nome_agenzia, indirizzo, tel, CF_partecipante, nome, cognome, data_nascita,<br />
e_mail, codice_materiale_partecipante, descr_materiale, num_foto, città_provino,<br />
nome_hotel_provino, data_provino, ora_provino, tipo_provino, esito_provino)<br />
Nell’ipotesi che ciascun provino è organizzato da un’agenzia e che una stessa persona possa<br />
partecipare a più provini, se ne determini la chiave e si individuino, esplicitandole, le dipendenze<br />
funzionali. Sulla base di queste si proceda alla normalizzazione in 3° forma normale, preservando le<br />
dip. Funzionali.<br />
Dominio\semantica dei dati: organizzazione dei provini delle Agenzie di casting italiane.<br />
Ipotesi della traccia: ciascun provino è organizzato da un’agenzia ed una stessa persona può<br />
partecipare a più provini<br />
Il dominio dei dati e le ipotesi forniscono le seguenti considerazioni: il dominio dei dati indica che è<br />
necessario individuare le agenzie ed i provini mentre secondo le ipotesi della traccia chi li organizza e<br />
chi vi partecipa.<br />
Primo passo: trovare tutte le dipendenze funzionali in accordo al dominio ed alle ipotesi. Passare alla<br />
seconda forma normale individuando eventuali attributi composti. In questo esercizio l’attributo<br />
indirizzo può essere considerato composto dai seguenti attributi: via, N_civico e CAP<br />
1) PIVA_agenzia nome_agenzia, via, N_civico, CAP, tel<br />
2) CF_partecipante nome, cognome, data_nascita, e-mail, codice_materiale_partecipante<br />
3) codice_materiale_partecipante descr_materiale, num_foto<br />
Ipotesi: consideriamo che un’agenzia in una città possa organizzare solo 1 provino al giorno.<br />
4) PIVA_agenzia, città_provino, data_provino nome_hotel_provino, tipo_provino<br />
Ipotesi: consideriamo ora_provino come l’ora in cui inizia la prova di ciascun partecipante.<br />
5) PIVA_agenzia, città_provino, data_provino, CF_partecipante ora_provino, esito_provino<br />
Secondo passo: individuare la chiave della tabella.<br />
In base alle dipendenze trovate ipotizziamo come chiave della tabella PIVA_agenzia, città_provino,<br />
data_provino, CF_partecipante<br />
Se tutte le dipendenze precedenti possono essere classificate rispetto alla suddetta chiave in uno dei<br />
seguenti modi:<br />
• dipendenza piena (la dip. 5);<br />
• dipendenza parziale (la dip. 1, 2, 4);
• dipendenza transitiva (la dip. 3);<br />
allora l’esercizio è svolto correttamente.<br />
Le tabelle risultanti sono:<br />
AGENZIA (PIVA_agenzia, nome_agenzia, via, N_civico, CAP, tel)<br />
PARTECIPANTE (CF_partecipante, nome, cognome, data_nascita, e-mail, codice_materiale_partecipante)<br />
MATERIALE (codice_materiale_partecipante, descr_materiale, num_foto)<br />
PROVINO (PIVA_agenzia, città_provino, data_provino, nome_hotel_provino, tipo_provino)<br />
PARTECIPA_PROVINO (PIVA_agenzia, città_provino, data_provino, CF_partecipante, ora_provino,<br />
esito_provino)<br />
<strong>Esercizi</strong>o d<br />
Date le seguenti relazioni:<br />
PROGETTO(Codice, nome, importo_mensile, data_inizio, data_consegna)<br />
DIPENDENTE(CF, nome, cognome, data_nascita, data_assunzione)<br />
LAVORA_SU(Codice, CF, num_ore, ruolo)<br />
esprimere in SQL le seguenti interrogazioni:<br />
1) Estrarre i responsabili dei progetti con un importo annuale superiore a 10000 euro ed un numero di<br />
ore complessivo superiore a 1000.<br />
SELECT distinct CF<br />
FROM LAVORA_SU natural join PROGETTO<br />
WHERE importo_mensile*12 > 10000<br />
AND ruolo = ‘responsabile’<br />
AND codice IN ( SELECT codice<br />
FROM LAVORA_SU<br />
GROUP BY codice<br />
HAVING sum(num_ore) > 1000 )<br />
2) Per ciascun dipendente, estrarre il numero di progetti su cui lavora attualmente con qualifica di<br />
‘programmatore’.<br />
SELECT CF, count(*)<br />
FROM LAVORA_SU natural join PROGETTO<br />
WHERE ruolo = ‘programmatore’<br />
AND data_inizio = ‘28/07/2006’<br />
GROUP BY CF
APPELLO 17 FEBBRAIO 2006<br />
<strong>Esercizi</strong>o a<br />
Si progetti uno schema concettuale Entità-Relazioni per lo scenario più sotto descritto.<br />
Una base di dati deve essere utilizzata dal comune di Bari per gestire alcuni dati relativi ai suoi<br />
cittadini.<br />
Ciascun cittadino è caratterizzato da un codice fiscale, dal nome e dal cognome, dalla data e dal<br />
comune di nascita, dal numero di telefono e dalla residenza. Inoltre, per ciascun cittadino,<br />
interessa conoscere i seguenti dati che ne definiscono il percorso formativo: occupazione attuale,<br />
titolo di studio con relativa votazione, elenco degli eventuali attestati posseduti con relativa data di<br />
conseguimento.<br />
Per gestire la sezione “Anagrafe” del comune, è necessario memorizzare i seguenti dati:<br />
i genitori di ciascun cittadino, i matrimoni e la relativa data, considerando che ciascun cittadino<br />
può sposarsi più volte ma non con la stessa persona.<br />
Per gestire la sezione “Catasto” del comune, è necessario memorizzare le proprietà di ciascun<br />
cittadino che sono caratterizzate da un identificativo catastale, una descrizione, un valore<br />
economico ed una categoria catastale (unità abitativa, unità commerciale, terreno). Per l’unità<br />
abitativa si deve tener traccia del numero di vani,mentre, per l’unità commerciale ed il terreno, la<br />
superficie (espressa in mq).<br />
Per gestire la sezione “Sanità” del comune, è necessario memorizzare le malattie particolarmente<br />
infettive da cui è attualmente, oppure è stato affetto, ciascun cittadino indicando, per ognuna, la<br />
data di inizio della cura e l’eventuale data di guarigione. Ciascuna malattia è identificata da un<br />
nome univoco, una descrizione, una classe (con valore non superiore a 4) e dal principio attivo che<br />
la cura. Si ipotizzi che nessun cittadino possa avere, per più di una volta, la stessa malattia.<br />
Indicare le cardinalità delle relazioni e un identificatore per ciascuna entità.<br />
Osservazioni:<br />
• Le ipotesi della traccia su matrimonio (ciascun cittadino può sposarsi più volte ma non con la<br />
stessa persona) e malattia (nessun cittadino può avere, per più di una volta, la stessa malattia)<br />
ci permettono di utilizzare delle relazioni N : N.<br />
• L’entità PERCORSO FORMATIVO non è necessaria poichè è possibile assegnare tutti i suoi<br />
attributi e relazioni direttamente all’entità CITTADINO.<br />
• L’espressione eventuale guarigione della traccia indica che il campo data_guarigione può<br />
essere NULL.<br />
• La specifica che la superficie è espressa in mq è un’indicazione per il tipo di dato in SQL da<br />
utilizzare per il campo mq nell’esercizio b.
Risoluzione della gerarchia: Aggiungere un attributo tipo (unità abitativa, terreno, unità<br />
commerciale) all’entità PROPRIETÀ e portare gli attributi dei figli (N_vani, mq) nell’entità padre.<br />
Per essere più precisi dovremmo aggiungere un ulteriore vincolo (check) chiedendo che:<br />
- N_vani ha un valore quando tipo = ‘unità abitativa’<br />
- Mq ha un valore quando tipo = ‘terreno’ oppure tipo = ‘unità commerciale’<br />
Business rules:<br />
1. la classe non può assumere un valore superiore a 4.<br />
2. tipo può assumere solo i 3 valori: ‘unità abitativa’, ‘terreno’, ‘unità commerciale’.
<strong>Esercizi</strong>o b<br />
Si definiscano le relazioni (tabelle) risultanti in SQL, avendo cura di esplicitare i vincoli di integrità.<br />
CITTADINO (CF, nome, cognome, data_nascita, comune_ nascita, residenza, tel, CF_padre,<br />
CF_madre)<br />
MATRIMONIO (CF_marito, CF_moglie, data)<br />
PERCORSO_FORMATIVO ( CF, occupazione, titolo, voto)<br />
ATTESTATO ( ID, NOME)<br />
PERCORSO_ATTESTATO ( CF, ID, data)<br />
PROPRIETÀ (ID_catasto, descrizione, valore, tipo, N_vani, mq, CF_proprietario)<br />
MALATTIA ( nome, descrizione, classe)<br />
CITTADINO_MALATTIA ( CF, malattia, data_inizio, data_guarigione)<br />
CREATE TABLE CITTADINO<br />
( CF char(16) primary key,<br />
nome varchar(30),<br />
cognome varchar(20),<br />
data_nascita date,<br />
comune_nascita varchar(50),<br />
residenza varchar(100),<br />
tel varchar(15),<br />
CF_padre char(16) references CITTADINO(CF),<br />
CF_madre char(16) references CITTADINO(CF) )<br />
CREATE TABLE PERCORSO_FORMATIVO<br />
( CF char(16) primary key,<br />
occupazione varchar(50),<br />
titolo varchar(50),<br />
voto smallint,<br />
foreign key(CF) references CITTADINO(CF)<br />
)<br />
CREATE TABLE PROPRIETÀ<br />
( ID_catasto char(10) primary key,<br />
descrizione varchar(100),<br />
valore numeric(9,2),<br />
tipo varchar (17) check (tipo IN (‘unità abitativa’, ‘terreno’, ‘unità commerciale’),<br />
N_vani smallint,<br />
mq float,<br />
CF_proprietario char(16) references CITTADINO(CF),<br />
check ( (N_vani IS NOT NULL AND tipo = ‘unità abitativa’) OR (mq IS NOT NULL AND tipo<br />
IN (‘terreno’,‘unità commerciale’)) )<br />
)
<strong>Esercizi</strong>o c<br />
Si vuole realizzare un database relativo alla alle programmazioni dei films delle reti televisive<br />
italiane. E’ stata a tal fine costruita, da un inesperto progettista, una unica tabella descritta dai<br />
seguenti attributi:<br />
(cod_film, titolo, regista, anno_produzione, data_programmazione_film, ora_inizio, ora_fine,<br />
nome_reteTV, tipo_rete, cod_pubblicità, nome_pubblicità, ora_trasmissione_pubblicità, durata)<br />
Considerando che alla programmazione di un film possono essere assegnate le stesse pubblicità,<br />
si determini la chiave della tabella e si individuino, esplicitandole, le dipendenze funzionali. Sulla<br />
base di queste si proceda alla normalizzazione in 3° forma normale, preservando le dip. Funzionali.<br />
Dominio\semantica dei dati: programmazioni dei films delle reti televisive italiane.<br />
Ipotesi della traccia: alla programmazione di un film possono essere assegnate le stesse pubblicità<br />
Il dominio dei dati e le ipotesi forniscono le seguenti considerazioni: il dominio dei dati indica che è<br />
necessario individuare i films, le reti televisive e le relative programmazioni mentre secondo le ipotesi<br />
della traccia le pubblicità e quando vengono trasmesse allinterno di un film in programmazione.<br />
Primo passo: trovare tutte le dipendenze funzionali in accordo al dominio ed alle ipotesi. Passare alla<br />
seconda forma normale individuando eventuali attributi composti.<br />
1) cod_film titolo, regista, anno_produzione<br />
2) nome_reteTV tipo_rete<br />
3) cod_pubblicità nome_pubblicità, durata<br />
Ipotesi: consideriamo che un film non possa essere trasmesso su una stessa rete più volte al giorno.<br />
4) cod_film, nome_reteTV, data_programmazione_film ora_inizio, ora_fine<br />
Ipotesi: consideriamo l’ipotesi della traccia.<br />
5) cod_film, nome_reteTV, data_programmazione_film, ora_trasmissione_pubblicità<br />
cod_pubblicità<br />
Secondo passo: individuare la chiave della tabella.<br />
Si verifichi che, se la chiave della tabella è cod_film, nome_reteTV, data_programmazione_film,<br />
ora_trasmissione_pubblicità, tutte le dipendenze funzionali precedenti possono essere classificate<br />
rispetto alla suddetta chiave in uno dei seguenti modi: dipendenza piena, dipendenza parziale,<br />
dipendenza transitiva.<br />
Le tabelle risultanti sono:<br />
FILM (cod_film, titolo, regista, anno_produzione)<br />
RETE (nome_reteTV, tipo_rete)<br />
PUBBLICITÀ (cod_pubblicità, nome_pubblicità, durata)
PROGRAMMAZIONE_FILM (cod_film, nome_reteTV, data_programmazione_film, ora_inizio,<br />
ora_fine)<br />
PROGRAMMAZIONE_PUBBLICITÀ (cod_film, nome_reteTV, data_programmazione_film,<br />
ora_trasmissione_pubblicità, cod_pubblicità)<br />
<strong>Esercizi</strong>o d<br />
Date le seguenti relazioni:<br />
PERSONA(CF, nome, cognome, data_nascita)<br />
CORSA(N_linea, ora_partenza, comune_partenza, ora_arrivo, comune_arrivo, num_km)<br />
PRENOTAZIONE(codice, data_prenotazione, CF, N_linea, ora_partenza, costo)<br />
esprimere in SQL le seguenti interrogazioni:<br />
1) Estrarre il comune di partenza, il comune di arrivo e la durata di tutte le corse prenotate da ‘Mario<br />
Rossi’.<br />
SELECT comune_partenza, comune_arrivo, ora_arrivo – ora_partenza<br />
FROM CORSA<br />
WHERE (N_linea, ora_partenza) IN ( SELECT N_linea, ora_partenza<br />
FROM PRENOTAZIONE natural join PERSONA<br />
WHERE nome = ‘Mario’<br />
AND cognome = ‘Rossi’<br />
)<br />
2) Estrarre i viaggiatori che hanno prenotato una stessa corsa almeno 2 volte ma mai una corsa in<br />
partenza da ‘Bari’.<br />
SELECT *<br />
FROM Persona<br />
WHERE CF IN ( SELECT distinct P1.CF<br />
FROM PRENOTAZIONE P1, PRENOTAZIONE P2<br />
WHERE P1.N_linea = P2.N_linea<br />
AND P1.ora_partenza = P2.ora_partenza<br />
AND P1.CF = P2.CF<br />
AND P1.codice P2.codice<br />
)<br />
AND CF NOT IN ( SELECT distinct CF<br />
FROM PRENOTAZIONE natural join CORSA<br />
WHERE comune_partenza = ‘Bari’<br />
)
APPELLO 12 FEBBRAIO 2008<br />
<strong>Esercizi</strong>o a<br />
Si progetti uno schema concettuale Entità-Relazioni per lo scenario più sotto descritto.<br />
Una base di dati deve essere utilizzata per gestire il calendario delle partite del prossimo campionato<br />
di calcio di serie A e di serie B.<br />
Bisogna, pertanto, tener traccia delle seguenti informazioni: gli stadi italiani, le squadre di calcio, i<br />
calciatori tesserati e le partite disputate. In particolare, si consideri che:<br />
• i calciatori che partecipano al campionato sono caratterizzati dai seguenti dati: numero di tessera,<br />
nome e cognome, data e paese di nascita. A ciascun giocatore è associato eventualmente un fan<br />
club di cui si vuole tener traccia mediante i seguenti dati: numero di iscritti, data di creazione,<br />
quota di partecipazione e sito internet;<br />
• gli stadi utilizzati durante il campionato che sono caratterizzati dai seguenti dati: codice<br />
alfanumerico univoco, nome, capienza e città;<br />
• le squadre che partecipano al campionato che sono caratterizzate dai seguenti dati: identificativo<br />
univoco, nome ed eventuale numero di scudetti vinti.<br />
Per gestire il calendario è necessario tener traccia delle partite disputate, che possono essere di serie A<br />
oppure di serie B, e che sono, inoltre, caratterizzate dai seguenti dati: data della partita, ora di inizio<br />
ed ora di fine, punteggio parziale alla fine del primo tempo e punteggio finale. Si osservi che è<br />
necessario verificare che ciascun punteggio sia costituito da una sequenza di caratteri di questo tipo<br />
‘0:0’. A ciascuna partita bisogna, inoltre, associare lo stadio di riferimento, la squadra che gioca in<br />
casa, la squadra ospite, l’arbitro della partita, di cui si conoscono i soli dati anagrafici, i calciatori<br />
della prima squadra ed i calciatori della seconda. Infine, per ciascun calciatore, sia esso della prima o<br />
della seconda squadra, è necessario tener traccia del ruolo e dell’eventuale numero di reti segnato in<br />
ogni partita e di un campo che indichi se il calciatore giochi come capitano in ciascuna delle partite<br />
disputate.<br />
Indicare le cardinalità delle relazioni e un identificatore per ciascuna entità.
N.B. era possibile anche considerare l’entità FUN CLUB come entità debole dall’entità CALCIATORE<br />
senza chiave parziale<br />
Business rules:<br />
1) punt_parziale e punt_finale devono essere stringhe di testo di questo tipo ‘_:_’<br />
2) serie può assumere i valori ‘A’ oppure ‘B’;<br />
3) capitano può assumere solo due valori (vero/falso oppure sì/no)<br />
4) il codice dello stadio è alfanumerico
<strong>Esercizi</strong>o b<br />
Si definiscano le relazioni (tabelle) risultanti in SQL, avendo cura di esplicitare i vincoli di integrità.<br />
Si riportano per brevità la definizione SQL solamente delle seguenti tabelle: FUN CLUB, PARTITA e<br />
GIOCA_CASA<br />
CREATE TABLE FUN CLUB<br />
(<br />
URL char(30) primary key,<br />
N_tessera char(8) references GIOCATORE (N_tessera),<br />
data_creazione date,<br />
N_iscritti int,<br />
quota_iscrizione numeric(6,2)<br />
)<br />
CREATE TABLE PARTITA<br />
(<br />
data date,<br />
codStadio char(8) references STADIO (codice),<br />
ora_in time,<br />
ora_fin time,<br />
punt_parziale char(3) check( punt_parziale LIKE ‘_:_’),<br />
punt_finale char(3) check( punt_finale LIKE ‘_:_’),<br />
serie char(1) check( serie IN (‘A’,’B’)),<br />
CFarbitro char(16) references ARBITRO (CF),<br />
squadra_ospite int references SQUADRA (codice),<br />
squadra_casa int references SQUADRA (codice),<br />
primary key (data, codStadio)<br />
)<br />
CREATE TABLE GIOCA_CASA<br />
(<br />
N_tessera char(8) references CALCIATORE (N_tessera),<br />
data date,<br />
codStadio char(8),<br />
ruolo varchar(30),<br />
capitano bit,<br />
N_reti,<br />
primary key (N_tessera, data, codStadio)<br />
foreign key(data, codStadio) references PARTITA(data, codStadio)<br />
)
<strong>Esercizi</strong>o c<br />
Si vuole realizzare un database relativo alla gestione delle consegne di una società di trasporti. E’ stata a<br />
tal fine costruita, da un inesperto progettista, un’unica tabella descritta dai seguenti attributi:<br />
(Targa_mezzo, data_immatricolazione, modello, N_patente, nome, cognome, data_nascita,<br />
livello_servizio, data_consegna, N_ord_consegna, N_colli_consegnati, PIVA_dettagliante,<br />
ragione_sociale, via, civico, città, provincia)<br />
Nell’ipotesi che un dettagliante possa ricevere una sola consegna al giorno e che l’attributo<br />
N_ord_consegna indica il numero progressivo assegnato a ciascun dettagliante/consegna per<br />
definire l’ordine delle consegne, se ne determini la chiave e si individuino, esplicitandole, le dipendenze<br />
funzionali. Sulla base di queste si proceda alla normalizzazione in 3° forma normale, preservando le dip.<br />
Funzionali.<br />
IPOTESI 1 - dettagliante possa ricevere una sola consegna al giorno<br />
IPOTESI 2 - N_ord_consegna indica il numero progressivo assegnato a ciascun<br />
dettagliante/consegna per definire l’ordine delle consegne<br />
(1) Targa_mezzo data_immatricolazione, modello<br />
(2) N_patente nome, cognome, data_nascita, livello_servizio<br />
Si osservi che il livello di servizio poteva anche essere associato ad ogni consegna piuttosto che al<br />
conducente<br />
(3) PIVA_dettagliante ragione_sociale, via, civico, città<br />
(4) Città provincia (nell’ipotesi che fissata la città determino univocamente la provincia)<br />
Per le ipotesi della traccia posso identificare univocamente una consegna con data_consegna e<br />
piva_dettagliante (IPOTESI 1) oppure con data_consegna e N_ord_consegna (IPOTESI 2).<br />
In particolare se fisso (soluzione A)<br />
(Data_consegna, piva_dettagliante) determino univocamente il numero d’ordine della relativa consegna<br />
(in termini di dipendenze funzionali avrò Data_consegna, piva_dettagliante N_ord_consegna)<br />
mentre se fisso (soluzione B)<br />
(Data_consegna, N_ord_consegna) determino univocamente la piva_dettagliante associata alla relativa<br />
consegna (in termini di dipendenze funzionali avrò Data_consegna, N_ord_consegna <br />
piva_dettagliante)<br />
In accordo alla soluzione A ottengo la seguente dipendenza funzionale<br />
(5) Data_consegna, piva_dettagliante N_ord_consegna, N_colli_consegnati, targa_mezzo, N_patente
La chiave della tabella risulta essere in questo caso (soluzione A): Data_consegna, piva_dettagliante<br />
Infine, si poteva anche ipotizzare che il numero d’ordine delle consegne fosse sempre lo stesso e non<br />
venisse calcolato di giorno in giorno. In questo caso l’attributo N_ord_consegna andava associato<br />
direttamente alla piva_dettagliante (PIVA_dettagliante ragione_sociale, via, civico, città,<br />
N_ord_consegna) e l’unica chiave possibile per la tabella diventava quella in accordo alla soluzione A<br />
<strong>Esercizi</strong>o d<br />
Date le seguenti relazioni:<br />
CLIENTE (CodCliente, nome, cognome, gg_nascita, mm_nascita, aa_nascita)<br />
PRODOTTO (CodProdotto, nome)<br />
ACQUISTO (CodAcquisto, gg_acquisto, mm_acquisto, aa_acquisto, ora_acquisto, CodCliente)<br />
PRODOTTI_ACQUISTATI(CodAcquisto, CodProdotto, Num_pezzi)<br />
esprimere in SQL le seguenti interrogazioni:<br />
1) Estrarre in ordine alfabetico i dati dei clienti che hanno fatto un acquisto il giorno del loro<br />
compleanno.<br />
SELECT distinct Cliente.*<br />
FROM Cliente natural join Acquisto<br />
WHERE gg_nascita=gg_acquisto<br />
AND mm_nascita=mm_acquisto<br />
ORDER BY cognome, nome<br />
Oppure<br />
SELECT *<br />
FROM Cliente C<br />
WHERE codCliente IN ( SELECT distinct codCliente<br />
FROM Acquisto<br />
WHERE mm_acquisto = C.gg_nascita<br />
AND mm_acquisto = C.mm_nascita)<br />
ORDER BY cognome, nome<br />
Oppure<br />
SELECT *<br />
FROM Cliente C<br />
WHERE (gg_nascita, mm_nascita) IN ( SELECT gg_acquisto, mm_acquisto<br />
FROM Acquisto<br />
WHERE codCliente = C.codCliente<br />
)<br />
ORDER BY cognome, nome
2) Selezionare i prodotti per i quali nel 2007 è stato venduto un numero di pezzi complessivo superiore a<br />
4000.<br />
SELECT *<br />
FROM Prodotto<br />
WHERE codProdotto IN ( SELECT codProdotto<br />
FROM Acquisto natural join Prodotti_acquistati<br />
WHERE aa_acquisto = 2007<br />
GROUP BY codProdotto<br />
HAVING sum(Num_pezzi) > 4000)<br />
Esempi di Normalizzazione<br />
1) Appello 7 Aprile 2006<br />
Si vuole realizzare un database relativo alla gestione delle chiamate di assistenza di un call center.<br />
E’ stata a tal fine costruita, da un inesperto progettista, un’unica tabella descritta dai seguenti attributi:<br />
(cod_operatore, nome, cognome, tipo_operatore, data_chiamata, ora_inizio, ora_fine, CF_cliente,<br />
nome, cognome, data_nascita, tipo_pagamento_assistenza, cod_assistenza,<br />
descrizione_cod_assistenza, costo_assistenza_chiamata)<br />
Ipotesi della traccia: ciascuna chiamata può soddisfare più problemi di assistenza<br />
1. cod_operatore → nome, cognome, tipo_operatore<br />
2. CF_cliente → nome, cognome, data_nascita<br />
3. cod_assistenza → descrizione_cod_assistenza<br />
Osservazione: Un operatore in un certo istante prenderà una sola chiamata e quindi fissati operatore,<br />
data ed ora risultano univocamente definiti anche il cliente che effettua la chiamata e l’ora di fine della<br />
stessa<br />
4. cod_operatore, data_chiamata, ora_inizio → ora_fine, CF_cliente<br />
Osservazione: secondo quanto indicato dalla traccia una stessa chiamata può risolvere più problemi di<br />
assistenza ossia fissata la chiamata è possibile avere N codici di assistenza diversi ed analogamente<br />
fissato un codice di assistenza questo può riferirsi ad N chiamate diverse pertanto si ottiene la seguente<br />
ultima dipendenza<br />
5. cod_operatore, data_chiamata, ora_inizio, cod_assistenza → tipo_pagamento,<br />
costo_assistenza_chiamata
Osservazione: Si è considerato il caso più generale in cui il costo_assistenza_chiamata sia il costo<br />
associato ad un problema di assistenza risolto durante una particolare chiamata<br />
Chiave della tabella: cod_operatore, data_chiamata, ora_inizio, cod_assistenza<br />
• dipendenza piena (la dip. 5);<br />
• dipendenza parziale (la dip. 1, 3, 4 );<br />
• dipendenza transitiva (la dip. 2).
2) Appello 23 Giugno 2006<br />
Si vuole realizzare un database relativo alla gestione delle valutazioni delle prove di un concorso. E’<br />
stata a tal fine costruita, da un inesperto progettista, un’unica tabella descritta dai seguenti attributi:<br />
(CF_partecipante, nome_p, cognome_p, data_nascita, laurea, num_titoli, CF_commissario, nome_c,<br />
cognome_c, titolo_c, codice_elaborato, ora_consegna, num_pagine, puntegg_elaborato,<br />
data_valutazione, ora_valutazione, punteggio_commissario)<br />
Ipotesi della traccia: ciascun elaborato è valutato da più commissari<br />
1. CF_partecipante → nome_p, cognome_p, data_nascita, laurea, num_titoli, codice_elaborato<br />
2. CF_commissario → nome_c, cognome_c, titolo_c<br />
3. codice_elaborato → ora_consegna, num_pagine, puntegg_elaborato<br />
Osservazione: consideriamo l’ipotesi della traccia ed il fatto che è plausibile supporre che un<br />
commissario valuti un elaborato una sola volta e che tale valutazione avverrà in una certa data ed ora<br />
4. CF_partecipante, CF_commissario → punteggio_commissario, data_valutazione, ora_valutazione<br />
Chiave della tabella: CF_partecipante, CF_commissario<br />
• dipendenza piena (la dip. 4);<br />
• dipendenza parziale (la dip. 1, 2 );<br />
• dipendenza transitiva (la dip. 3).
3) Appello 28 Settembre 2006<br />
Si vuole realizzare un database relativo alla gestione dei contratti di affitto dei posti auto di un<br />
autosilo. E’ stata a tal fine costruita, da un inesperto progettista, un’unica tabella descritta dai seguenti<br />
attributi:<br />
(N_patente, data_rilascio, nome, cognome, cellulare, N_targa, modello, colore,<br />
anno_immatricolazione, stato_auto, num_piano, num_box, data_inizio_contratto, data_fine_contratto,<br />
prezzo_affitto)<br />
1. N_patente → data_rilascio, nome, cognome, cellulare<br />
2. N_targa → modello, colore, anno_immatricolazione<br />
3. num_box → num_piano<br />
4. N_targa, data_inizio_contratto → data_fine_contratto, prezzo_affitto, N_patente, num_box,<br />
stato_auto<br />
Osservazione: Si è considerato il caso più generale in cui il proprietario varia nel tempo altrimenti si<br />
poteva anche far dipendere N_patente da N_targa<br />
Chiave della tabella: N_targa, data_inizio_contratto<br />
• dipendenza piena (la dip. 4);<br />
• dipendenza parziale (la dip. 2);<br />
• dipendenza transitiva (la dip. 1,3).
ESEMPI di query SQL<br />
1) Appello 21 Novembre 2006<br />
d) Date le seguenti relazioni:<br />
CONTROLLORE (CF, nome, cognome, data_nascita, codice)<br />
CONTROLLO_AZIENDA (data_controllo, CF_controllore, ora, azienda_riferimento)<br />
RISULTATI_ANALISI_BOVINO ((Data_controllo, CF_controllore, ID_bovino, proteine, lattosio, grasso)<br />
esprimere in SQL le seguenti interrogazioni:<br />
1) Estrarre i dati relativi a 2 controlli: il primo è quello in data odierna ed il secondo è quello<br />
immediatamente precedente.<br />
I soluzione che considera un ordine temporale basato solo sulla data<br />
SELECT *<br />
FROM controllo_azienda<br />
WHERE data_controllo = '21-11-2006'<br />
OR data_controllo = (SELECT max(data_controllo)<br />
FROM controllo_azienda<br />
WHERE data_controllo < '21-11-2006')<br />
II soluzione che considera un ordine temporale basato sulla data e sull’ora<br />
select *<br />
from controllo_azienda<br />
where data_controllo = '21-11-2006'<br />
AND ora=(select max(ora)<br />
from controllo_azienda<br />
where data_controllo = '21-11-2006')<br />
UNION<br />
select *<br />
from controllo_azienda<br />
where (data_controllo, ora) = (select max(data_controllo),max(ora)<br />
from controllo_azienda<br />
where (data_controllo = '21-11-2006'<br />
AND ora1 < (select ora<br />
from controllo_azienda<br />
where (data_controllo, ora) = (select max(data_controllo), max(ora)<br />
from controllo_azienda<br />
where data_controllo = '21-11-2006')))<br />
OR<br />
(data_controllo = (select max(data_controllo)<br />
from controllo_azienda<br />
where data_controllo < '21-11-2006'))<br />
)
2) Estrarre i controllori che hanno partecipato a controlli per cui si è avuto un valor medio in grasso<br />
pari a 4.5 ed un valor medio in proteine superiore a 4.<br />
SELECT *<br />
FROM controllore<br />
Where CF IN (SELECT distinct CF_controllore<br />
FROM risultati_analisi_bovino<br />
GROUP BY data_controllo, CF_controllore<br />
HAVING avg(grasso) = 4.5 AND avg (proteine) > 4)<br />
2) Appello 28 Settembre 2006<br />
d) Date le seguenti relazioni:<br />
GIOCATORE (N_tessera, nome, cognome, data_nascita, squadra_attuale)<br />
PARTITA (Codice, squadra1, squadra2, campionato, punteggio1, punteggio2)<br />
GIOCATA (Codice, N_tessera, num_reti)<br />
esprimere in SQL la seguente interrogazione:<br />
1) Estrarre i dati del capocannoniere del campionato 2004/2005.<br />
SELECT *<br />
FROM giocatore<br />
WHERE N_tessera IN ( SELECT N_tessera<br />
FROM partita NATURAL JOIN giocata<br />
WHERE campionato = '2004-2005'<br />
GROUP BY N_tessera<br />
HAVING sum(num_reti) >= ALL (SELECT sum(num_reti)<br />
FROM partita NATURAL JOIN giocata<br />
WHERE campionato = '2004-2005'<br />
GROUP BY N_tessera))
3) Appello 24 Settembre 2005 ed Esempi vari<br />
Date le seguenti relazioni:<br />
GUIDATORE ( CF, nome, cognome, età, N_patente)<br />
AUTO ( Targa, data_immatricolazione, modello, CF_guidatore)<br />
INCIDENTE ( Codice, anno, data_ora_riferimento, indirizzo, num_auto_coinvolte, num_feriti)<br />
AUTO_INCIDENTE ( Codice, anno, targa)<br />
esprimere in SQL le seguenti interrogazioni:<br />
1) Selezionare, per ciascun incidente, l’età media dei guidatori coinvolti.<br />
SELECT Codice,anno,avg(eta)<br />
FROM guidatore,auto,auto_incidente<br />
WHERE CF=CF_guidatore AND auto.Targa=auto_incidente.targa<br />
GROUP BY Codice,anno;<br />
2) Selezionare il numero di auto coinvolte ed il numero di feriti del primo e dell’ultimo incidente (su<br />
base temporale) memorizzati nella base di dati .<br />
SELECT num_auto_coinvolte, num_feriti, data_ora_riferimento<br />
FROM incidente<br />
WHERE data_ora_riferimento = (select max(data_ora_riferimento) from incidente)<br />
OR data_ora_riferimento = (select min(data_ora_riferimento) from incidente)<br />
Oppure<br />
SELECT num_auto_coinvolte, num_feriti<br />
FROM incidente<br />
WHERE data_ora_riferimento >= ALL (select data_ora_riferimento from incidente)<br />
OR data_ora_riferimento = ALL (SELECT count(*)<br />
FROM guidatore,auto,auto_incidente<br />
WHERE CF=CF_guidatore AND auto.Targa=auto_incidente.targa<br />
GROUP BY CF);
4) Mostrare i guidatori che non sono mai stati coinvolti in incidenti.<br />
SELECT *<br />
FROM guidatore<br />
WHERE CF NOT IN (SELECT distinct CF_guidatore<br />
FROM auto natural join auto_incidente)<br />
5) Selezionare le auto e l’età del relativo guidatore che non hanno fatto più di due incidenti.<br />
SELECT Targa, modello, eta<br />
FROM guidatore,auto<br />
WHERE CF=CF_guidatore AND targa IN (SELECT targa<br />
FROM auto_incidente<br />
GROUP BY targa<br />
HAVING count(*)