Sei sulla pagina 1di 25

16/01/2022

Derivazione dello schema E/R


Se lo schema ER è fatto giusto, da qui è tutto facile. cit. Suriani

Definizione e caratteristiche di una tabella


Modello Relazionale: proposto nel 1970 e si basa sulla parola “relazione”. Noi non la
useremo, siccome nel modello relazionale la parola significa “tabella”. Noi useremo la parola
“tabella” per le tabelle e “relazione” per le associazioni tra le tabelle.

Dati due insiemi D1 e D2, non necessariamente disgiunti, una relazione R definita su D1 e D2
è un qualunque sottoinsieme del prodotto cartesiano.

Ogni tabella ha un insieme di attributi e un insieme di righe (ennuple, record, n-uple).


L’elemento fondamentale sono le tabelle.

Per identificare un record di una tabella, abbiamo bisogno di un identificatore, ovvero la


chiave primaria. L’insieme minimo di attributi che identifica univocamente un record.
Le chiavi primarie creeranno il file degli indici, più indici abbiamo, più il database è legato e
non ce ne devono essere né troppi né troppi pochi.
Esiste sempre una chiave primaria poiché non possono esistere record uguali in una tabella.

Gli attributi che sono chiavi primarie, non possono assumere il valore null, quindi
devono sempre essere attributi obbligatori e non opzionali.

Oltre alla creazione di una chiave primaria, si creano anche chiavi esterne. Queste non
esistono fisicamente nella tabella ma vengono usate per fare collegamenti logici.

Ogni attributo ha un dominio che rappresenta i valori che può assumere.

Di una tabella è definito grado di una tabella il numero delle colonne (degli attributi). Mentre
è definita cardinalità il numero delle righe (dei record).

Regole di derivazione dallo schema E/R allo schema logico


Il modello logico dipende da come andiamo a rappresentare i dati nel nostro DBMS.

Regola 1. Ogni entità diventa una tabella. Ogni attributo dell’entità diventa un campo. La
chiave primaria che abbiamo individuato diventa la chiave primaria della tabella.

Dopo aver rappresentato la tabella (nei due metodi scritti sotto), dobbiamo rappresentare il
dominio, quindi scriviamo all’interno di una tabella con nome campo (nome dell’attributo),
descrizione (che cosa indica), tipo (stringa, numerico, ecc…), lunghezza (byte) e chiave
(ovvero che tipo di chiave è). Questa parte non viene richiesta dalla prof. Suriani.

Regola 2. Ogni relazione va rappresentata in modo diverso in base al tipo di relazione (1 a


1, 1 a N, N a N).
1 a 1: si risolve facendo migrare la chiave primaria di una delle due tabelle
create nell’altra. Quindi aggiungiamo (facciamo migrare) la chiave primaria di una tabella
negli attributi dell’altra (la facciamo migrare solo su UNA entità non su entrambe). Quindi
dobbiamo capire quale far migrare in base a quello che ci serve sapere.

In base alla situazione, la chiave che facciamo migrare non ha importanza (una come
l’altra). Ci sono situazioni in cui invece la chiave da far migrare è importante, se abbiamo
una relazione che non è totale in entrambe le relazioni, la chiave da far migrare sarà quella
dell'entità con partecipazione parziale (in modo da non avere mai una chiave esterna nulla).

Se lo facessimo per entrambe le entità, quindi facciamo migrare la chiave primaria di E1 su


E2 e di E2 su E1, creiamo un vincolo che non fa funzionare il sistema. Perché non posso
inserire nessun dato siccome per inserire un record su E1 ho bisogno di un record E2 ma per
inserire un record su E2 ho bisogno di un record su E1. RICORDA: Le chiavi (primarie o
esterne) sono sempre obbligatorie e non possono mai avere valore null quando viene
aggiunto un record.

1 a N: In questo caso è necessario aggiungere la chiave primaria dell’entità con


cardinalità N sulla tabella dell’entità con cardinalità 1. Quindi se E1 ha cardinalità 1
mentre E2 ha cardinalità N, aggiungo la chiave primaria di E1 (che diventa chiave esterna)
nella tabella di E2.

N a N: Si crea una nuova tabella in cui sono inserite le chiavi primarie delle due
entità e, se presenti, gli attributi della relazione. Quando risolvo la relazione creo una tabella
con lo stesso nome dell’associazione, in questo modo è come se creassi una nuova entità
che ha relazione 1 a N con le due entità e quindi la risolvo aggiungendo la chiave primaria di
entrambe le entità nella nuova tabella (se la relazione ha attributi, li aggiungo alla tabella
come campi) che formano la chiave primaria di quel record (che quindi è composta e non
singola).

Se ci sono associazioni ricorsive, la soluzione dipende sempre dalla cardinalità e funzionano


allo stesso modo, semplicemente le chiavi aggiunte appartengono alla stessa tabella ma
(probabilmente) ad un record diverso.

Se ci sono relazioni multiple (più relazioni tra due entità) si risolve esattamente come le altre
ma aggiungerò più chiavi quando devo farle migrare (siccome ho più relazioni).

Se ci sono più di 2 unità in una relazione (può essere solo N a N la relazione) si crea una
nuova tabella con le chiavi primarie delle varie entità (esattamente come le altre relazioni N
a N).

Abbiamo 2 modi per rappresentare una tabella nello schema logico:

Metodo 1

Nome Descrizione Prezzo

Metodo 2 (<-- meglio questa)

Tabella (Nome, Descrizione, Prezzo)


Esempio di come fare una derivazione dallo
schema E/R

Prima fase
Controllare le ridondanze ed eliminarle, semplificare i rapporti 1 a 1 e togliere le gerarchie.

Seconda fase
La prima cosa da fare è tradurre ogni entità in una tabella. Quindi si scrivono ogni attributo e
il nome della tabella, NON chiudo le parentesi perché dovrò aggiungere altre informazioni.

Docente (Id, Nome, Cognome, Dipartimento

Corso (Codice, Numero, Id (La chiave primaria dell’entità a 1, migra su quella con entità a N)

Studente (Matricola, Nome, Cognome

Frequenta (Codice, Matricola) (Perché è una relazione N a N, formano una nuova tabella, gli
attributi sono chiavi esterne ed insieme formano la chiave primaria)

LE CHIAVI ESTERNE SONO SOTTOLINEATE IN MODO TRATTEGGIATO, RICORDALO

30/01/2023

Correzione verifica 26/01


Se 3 entità sono collegate in modo indiretto, i 2 estremi non vanno collegati in modo diretto.
Non ci sono sottoentità (ovvero entità che “derivano” da una sola), non abbiamo e non
faremo le gerarchie; si sostituisce mettendo un campo che determina quale delle
“sottoentità” è quell’istanza. Quando si usa “id” come chiave primaria, aggiungere sempre
dopo “id” il nome (es. id_abbonato).

Le entità sono: Abbonamento, Abbonato, Pubblicazione, Articolo, Argomento.


RICORDA ^^^^

Schema E/R

Abbonamento
Ha id_abbonamento, data e periodo (trimestrale, semestrale o annuale). id_abbonamento è
la chiave primaria.

Abbonamento - Abbonato: partecipazione totale da entrambe le entità. Un abbonato può


fare N abbonamenti, un abbonamento è relativo ad 1 abbonato.
Abbonamento - Pubblicazione: la partecipazione è totale per abbonamento (deve) e
parziale per Pubblicazione (può). Un abbonamento è relativo ad 1 pubblicazione, una
pubblicazione può avere N abbonamenti.

Pubblicazione
Ha id_pubblicazione, titolo, prezzo, periodicita. id_pubblicazione è la chiave primaria.

Pubblicazione - Argomento: la partecipazione è totale per la pubblicazione (deve) e


parziale per l’argomento (può). La pubblicazione può trattare N argomenti, un argomento
può essere trattato da N pubblicazioni.

Pubblicazione - Articolo: la partecipazione è totale da entrambe le entità. Una


pubblicazione è formata da N articoli, un articolo forma 1 pubblicazione. Questa
associazione ha l’attributo data

Articolo
Ha id_articolo, titolo e testo. id_articolo è la chiave primaria.

Pubblicazione - Articolo: la partecipazione è totale da entrambe le entità. Una


pubblicazione è formata da N articoli, un articolo forma 1 pubblicazione. Questa
associazione ha l’attributo data.

Abbonato
Ha id_abbonato e tutta l’anagrafica. id_abbonato è la chiave primaria.

Abbonamento - Abbonato: partecipazione totale da entrambe le entità. Un abbonato può


fare N abbonamenti, un abbonamento è relativo ad 1 abbonato.

Argomento
Ha id_argomento e nome. id_argomento è la chiave primaria.

Pubblicazione - Argomento: la partecipazione è totale per la pubblicazione (deve) e


parziale per l’argomento (può). La pubblicazione può trattare N argomenti, un argomento
può essere trattato da N pubblicazioni.

Opzione 2
L’abbonamento non è un’entità ma un’associazione tra pubblicazione ed abbonato con gli
attributi dell’entità abbonamento.

Schema Logico
Abbonato(id_abbonato, nome, cognome, data_nasc, email, indirizzo)

Abbonamento(id_abb, periodo, data, id_abbonato, id_pubb)

Pubblicazione(id_pubb, titolo, periodicita, prezzo)


Argomento(id_argomento, nome)

Articolo(id_articolo, titolo, testo, data, id_pubb)

Tratta(id_pubb, id_argomento)

06/02/2023

Lo schema logico e linguaggio SQL


Usiamo il linguaggio SQL (Structured Query Language) per tradurlo e di conseguenza il
DML, DDL e DCL. Il linguaggio non è case sensitive.

Grazie all’SQL possiamo fare le operazioni di CRUD: Create Read Update Delete. I
linguaggi che mette a disposizione sono: DDL (Data Definition Language), DML (Data
Manipulation Language) e DCL (Data Control Language). L’SQL non è un linguaggio
procedurale.

DDL
Data Definition Language.

CHAR, CHAR(N), VARCHAR(N) sono tutti tipi di stringa. CHAR è un singolo carattere,
CHAR(N) è una stringa di caratteri di lunghezza fissa (N indica la lunghezza della stringa),
VARCHAR(N) è una stringa di lunghezza variabile (N indica il massimo della lunghezza
della stringa).

BIT indica un boolean, è un singolo bit.

INT(N), FLOAT(P) indicano valori numerici. N e P indicano la lunghezza massima.

DATE indica la data in formato AAAA/MM/GG o AAAA-MM-GG.

TIME indica l'ora nel formato ora, minuti, secondi e millisecondi.

TIMESTAMP indica la data nel formato anno, mese, giorno, ora, minuti, secondi e
millisecondi.

BLOB si può usare per inserire le immagini MA solitamente si indica solo il path per le
immagini, non vengono caricate nel database.

Comandi del DDL


Partendo dal seguente schema logico:

Studente(Matricola, Nome, Cognome) Voto(Id_voto, Voto, Data, Descrizione, Matricola)

I comandi che ci fornisce il linguaggio DDL sono i seguenti:

CREATE serve a creare tabelle, schemi, vincoli, nuovi domini e assertion;


ALTER serve a modificare lo schema di una tabella, aggiungendo nuovi attributi o
cancellando uno o più attributi preesistenti.

DROP serve a cancellare una tabella, un database o dei vincoli.

Iniziamo a creare lo schema fisico:

Il primo comando è:

CREATE DATABASE <NomeDatabase>

Poi devo creare delle tabelle con dei vincoli:

CREATE TABLE <NomeTabella> (


<Attributo> <tipo> [<Vincolo>],
<Attributo> <tipo> [<Vincolo>],
<Attributo> <tipo> [<Vincolo>]
);

I vincoli che esistono sono questi:

● PRIMARY KEY: definisce uno o più attributi come chiave primaria;


● UNIQUE: definisce uno o più attributi che identificano ogni tupla (istanza) NON E’
UNA CHIAVE PRIMARIA;
● NOT NULL: definisce uno o più attributi che sono obbligatori;
● DEFAULT: definisce un valore di default per uno o più attributi;
● CHECK: definisce dei vincoli su uno o più attributi;
● REFERENCE KEY: definisce vincoli fra attributi di diverse tabelle.

07/02/2023

I vincoli hanno diverso tipo:

● vincoli di dominio, un vincolo in un attributo;


● vincolo di tabella, un vincolo all’interno della tabella;
● vincolo interrelazionali, un vincolo tra diverse tabelle.

Per i vincoli di dominio si può usare il CHECK si possono usare:

● IN: uno dei valori indicati;


● BETWEEN: tra un valore massimo e minimo;
● NOT BETWEEN: non è tra un valore massimo e minimo;
● LIKE: deve essere strutturato in una maniera precisa (% indica dove inizia il valore
del campo);
● NOT LIKE: non deve essere strutturato in una maniera precisa.

SQL però non permette di usare CHECK in questo modo. Al suo posto, si usa ENUM che
corrisponde solo a IN.

I vincoli di tabella sono:

● PRIMARY KEY: indica la chiave primaria;


● UNIQUE: il valore non deve ripetersi;
● CHECK: come sopra ma controlla più campi, non solo uno.

13/02/2023

I vincoli tra tabelle sono strutturati così:

vincolo (campo) REFERENCES nome_tabella(campo)

Il vincolo possibile è REFERENCE_KEY.

ALTER:

Aggiungere un campo, cancellare un campo, modificare il tipo.

DROP:

Cancella una tabella, tutto. La sintassi è:

DROP nome_tabella RESTRICT o CASCADE o SET NULL

DML

Comandi del DML


INSERT:

Inserire un dato in una tabella. La sintassi è:

INSERT INTO nome_tabella nome_campo1, nome_campo2,... VALUES (valore1,valore2,...)

UPDATE:

Aggiornare un valore. La sintassi è:

UPDATE nome_tabella
SET campo1 = valore1
campo2 = valore2

WHERE condizione;

DELETE:

Cancella i valori, non lo schema (cosa che fa il DROP). La sintassi è:

DELETE FROM nome_tabella


WHERE condizione;

Algebra relazionale
Operatori relazionali, agiscono sulle tabelle, simili agli operatori degli insiemi. Possono
essere unari (una tabella) o binari (due tabelle).
Le operazioni binarie sono: unione, intersezione, differenza, ecc…
Le operazioni unarie sono: selezione e proiezione.
Le operazioni che usano più tabella sono: grafico cartesiano e

SELEZIONE usa l’operatore sigma (σ) mentre per la PROIEZIONE si usa il pigreco (π).

PRODOTTO CARTESIANO “per” ()CONGIUNZIONE due triangoli che si baciano


UNIONE (U)
INTERSEZIONE U al contrario
DIFFERENZA (-)

Operatori insiemistici binari


L’UNIONE unisce 2 tabelle

Si può fare solo tra tabelle con lo stesso schema. E i record uguali tra le due tabelle
vengono ridotti, ne rimane solo 1. Il risultato è una tabella con lo stesso schema ma con i
valori di entrambe le tabelle. Quindi con cardinalità maggiore o uguale a quelle di partenza.

L’INTERSEZIONE trova le parti in comune di 2 tabella


Si può fare solo tra tabelle con lo stesso schema. Crea una tabella con i record che sono
presenti in modo uguale tra le due tabelle. La cardinalità è minore o uguale a quella di
partenza.

La DIFFERENZA prende le parti uniche in una delle tabelle

Si può fare solo tra tabelle con lo stesso schema. Crea una tabella con i record che non
sono presenti nella seconda ma solo nella prima. La cardinalità è minore o uguale a quella di
partenza.

Operatori logici unari


La SELEZIONE serve a selezionare record che rispettano una condizione.

Crea una tabella con grado uguale ma cardinalità minore o uguale a quella di partenza.
TAGLIO ORIZZONTALE.

R = σP T indica che stiamo facendo una selezione con condizione P sulla tabella T, che
genera la tabella R.

La PROIEZIONE serve a eliminare le colonne che non ci interessano, secondo quella che
indichiamo.

Crea una tabella con cardinalità uguale e grado minore a quello di partenza.
TAGLIO VERTICALE.

R = πL A indica che stiamo facendo una proiezione sulla tabella A con condizione L e la
mettiamo nella tabella R.
27/02/2023

Il Prodotto Cartesiano
Natural Join

Si applica a 2 tabelle. Prende l’insieme dei record del primo elemento e lo mette in relazione
con ogni record del secondo elemento e viceversa.

Praticamente collego ogni elemento del primo con ogni elemento del secondo, quindi la
cardinalità sarà la moltiplicazione tra le due cardinalità e il grado la somma dei due gradi.

Inner Join

Si applica tra 2 tabelle con un attributo in comune (chiave esterna). Fa la stessa cosa del
natural join ma si prendono solo le tuple in cui è presente l’attributo uguale tra le
tabelle.

Il grado è la somma dei gradi delle tabelle a cui sottraggo 1 (non duplico il campo
dell’attributo in comune). La cardinalità è minore del prodotto tra le 2 cardinalità.

R = A ⨝ B indica che stiamo facendo un inner join della tabella A con la tabella B e la
mettiamo nella tabella R.

SELECT dipendente.CodDip,nome,cognome
FROM prenotazione
INNER JOIN dipendente ON dipendente.CodDip = prenotazione.CodDip
WHERE nCamera = 25

13/03/2023

Funzioni di Aggregazione
SI applicano ad una colonna di una tabella

Le funzioni sono: COUNT, MIN, MAX, SUM, AVG.


COUNT: Conta il numero di tuple con quella colonna.
MIN: Minimo del campo.
MAX: Massimo del campo.
SUM: Somma dei valori del campo.
AVG: Media del campo.

SELECT AVG(Stipendio) AS StipMedio


FROM DIPENDENTE

AS rinomina il campo che prendiamo.


CINEMA(CodiceCinema, Nome, Posti, Citta). Dobbiamo effettuare le seguenti interrogazioni:

1. Visualizzare il numero totale di posti nei cinema di Perugia.


a. SELECT SUM(Posti) AS PostiTot
FROM CINEMA
WHERE Citta = “Perugia”
2. Visualizzare il numero di cinema nella città di Perugia con meno di 100 posti
a. SELECT COUNT(*) AS Totale_Cinema
FROM CINEMA
WHERE Citta = “Perugia” AND Posti < 100

Funzioni di raggruppamento

GROUP BY <AttributoN> [HAVING <Condizione>]

DIPENDENTE(CodDip, Cognome, Nome, Livello, Stipendio)

1. Raggruppare i dipendenti in base al livello e calcolare lo stipendio medio per livello


a. SELECT Livello, AVG(Stipendio)
FROM DIPENDENTE
GROUP BY Livello

L’attributo con cui raggruppo deve sempre essere negli attributi della
select
2. Raggruppare i dipendenti in base al livello, sapere lo stipendio medio e conoscere il
numero di dipendenti di quel livello
a. SELECT Livello, AVG(Stipendio), COUNT(*)
FROM DIPENDENTE
GROUP BY Livello
3. Visualizzare per ogni livello e per ogni importo di stipendio, quanti dipendenti
ricevono quello stipendio
a. SELECT Livello, Stipendio, COUNT(*)
FROM DIPENDENTE
GROUP BY Livello, Stipendio
4. Per i dipendenti dei livelli maggiori del quinto, raggrupparli in base al loro livello,
conoscere lo stipendio medio ed il numero di dipendenti per livello
a. SELECT Livello, AVG(Stipendio), COUNT(*)
FROM DIPENDENTE
WHERE Livello > 5
GROUP BY Livello

WHERE non può essere messa dopo il GROUP BY.


Però le condizioni complesse (tipo AVG > 200) dobbiamo metterle per
forza nell’HAVING e non nel WHERE.
5. Per i livello con più di un dipendente, visualizzare lo stipendio medio ed il numero di
dipendenti per livello
a. SELECT Livello, COUNT(*), AVG(Stipendio)
FROM DIPENDENTE
GROUP BY Livello
HAVING COUNT(*) > 1
6. Per i livelli maggiori del quinto che hanno più di un dipendente, visualizzare lo
stipendio medio ed il numero di dipendenti per livelli
a. SELECT Livello, COUNT(*), AVG(Stipendio)
FROM DIPENDENTI
WHERE Livello > 5
GROUP BY Livello
HAVING COUNT(*) > 1

CINEMA(CodiceCinema, Nome, Posti, Citta)


FILM(CodiceFilm, Titolo, AnnoProduzione, LuogoProduzione, CognomeRegista, Genere)

1. Visualizza il numero totale di cinema presenti in ogni citta


a. SELECT Citta, COUNT(*)
FROM CINEMA
GROUP BY Citta
2. Visualizza il numero di cinema che hanno meno di 200 posti presenti in ogni citta
a. SELECT Citta, COUNT(*)
FROM CINEMA
WHERE Posti < 200
GROUP BY Citta
3. Visualizzare il numero di film prodotti dopo il 2000 in ogni luogo di produzione
a. SELECT LuogoProduzione, COUNT(*)
FROM FILM
WHERE AnnoProduzione > 2000
GROUP BY LuogoProduzione

16/03/2023

7.

SELECT D.*
FROM Dipendenti AS D
INNER JOIN Prenotazioni AS P
ON D.Cod_dip = P.Cod_dip
WHERE P.Camera = 25

SELECT D.*, P.*


FROM Dipendenti AS D
INNER JOIN Prenotazioni AS P
ON D.Cod_dip = P.Cod_dip
WHERE D.Eta BETWEEN 25 AND 40
SELECT A.Nome, A.Citta, P.Camera, P.Giorni, D.nome
FROM Prenotazioni AS P
INNER JOIN Alberghi AS A
ON P.Cod_alb = A.Cod_alb
INNER JOIN Dipendeti AS D
ON P.Cod_dip = D.Cod_dip
WHERE D.Citta = “Milano”

SELECT D.Cognome, D.nome, P.acconto, P.Camera


FROM Dipentendi AS D
INNER JOIN Prenotazione AS P
ON D.Cod_dip = P.Cod_dip
WHERE P.Acconto > 100000 AND D.Eta > 25

SELECT D.Nome, D.Cognome, A.Nome, A.Citta, AVG(P.Acconto)


FROM Dipendenti AS D
INNER JOIN Prenotazioni AS P
ON D.Cod_dip = P.Cod_dip
INNER JOI Alberghi AS A
ON P.Cod_alb = A.Cod_alb
GROUP BY A.Cod_alb
HAVING AVG(P.Acconto) < P.Acconto

20/03/2023

Esempi di query

ATTORI (CodAttore, Nome, AnnoNascita, Nazionalita)


RECITA (CodAttore*, CodFilm*)
FILM (CodFilm, Titolo, AnnoProduzione, Nazionalita, Regista, Genere)
PROIEZIONI (CodProiezione, CodFilm*, CodSala*, Incasso, DataProiezione)
SALA (CodSala, Posti, Nome, Citta)

1. Il titolo dei film di fantascienza, o giapponesi prodotti dopo il 1990 o i film francesi

a. SELECT Titolo
FROM Film
WHERE Genere = “Fantascienza” AND
((AnnoProduzione > 1990 AND Nazionalita = “Giapponese”) OR
Nazionalita = “Francese”)

b. π Titolo (𝜎 (da Genere a “Francese”)) Film)

2. Il titolo ed il genere dei film proiettati il giorno di natale del 2004

a. SELECT DISTINCT F.Titolo, F.Genere


FROM Film AS F
INNER JOIN Proiezioni AS P
ON P.CodFilm = F.CodFilm
WHERE DataProiezione = “25/12/2004”

DISTINCT serve a mostrare solo i film diversi e non 2 film uguali.

b. π Titolo, Genere (𝜎 DataProiezione = 25/12/2004 (Film⨝Proiezioni))

3. Il numero di sale di Pisa con più di 60 posti

a. SELECT COUNT(*)
FROM Sale
WHERE Posti > 60 AND Citta = “Pisa”

4. ∀ città il numero di sale con più di 60 posti

a. SELECT COUNT(*), Citta


FROM Sale
WHERE Posti > 60
GROUP BY Citta

5. ∀ regista l’incasso totale di tutte le proiezioni dei suoi film

a. SELECT SUM(P.Incasso) AS Incasso_Totale, F.Regista


FROM Film F
INNER JOIN Proiezioni P
ON P.CodFilm = F.CodFilm
GROUP BY F.Regista

6. ∀ regista e ∀ attore, il numero di film del regista con quell’attore

a. SELECT COUNT(*), F.Regista, A.Nome, A.CodAttore


FROM Film F
INNER JOIN Recita R
ON R.CodFilm = F.CodFilm
INNER JOIN Attori A
ON A.CodAttore = R.CodAttore
GROUP BY F.Regista, A.Nome, A.CodAttore

7. ∀ film di fantascienza che non è mai stato proiettato prima del 1/1/1970 il titolo e
l’incasso totale di tutte le sue proiezioni

a. SELECT F.CodFilm, F.Titolo, SUM(P.Incasso)


FROM Film F
INNER JOIN Proiezioni P
ON P.CodFilm = F.CodFilm
WHERE F.Genere = “Fantascienza”
GROUP BY F.CodFilm
HAVING MIN(P.DataProiezione) > “1/1/1970”

Siccome non deve essere MAI stato proiettato dopo, devo prendere la data
più vecchia e controllare solo quella

8. ∀ sala di Pisa che nel mese di gennaio 2020 ha incassato più di 20000 euro, il nome
della sala e l’incasso totale (gennaio 2020).

a. SELECT S.CodSala, S.Nome, SUM(P.Incasso)


FROM Sale S
INNER JOIN Proiezioni P
ON P.CodSala = S.CodSala
WHERE Citta = “Pisa” AND P.DataProiezione BETWEEN “1/1/2020” AND
“31/1/2020”
GROUP BY S.CodSala
HAVING SUM(P.Incasso) > 20000

9. Il numero di attori dei film in cui appaiono solo attori nati prima del 1970

a. SELECT COUNT(*) AS Numero_Attori, F.CodFilm


FROM Attori A
INNER JOIN Recita R
ON R.CodAttore = A.CodAttore
INNER JOIN Film
ON F.CodFilm = R.CodFilm
GROUP BY F.CodFilm
HAVING MAX(A.DataNascita) < “1/1/1970”
27/03/2023

Comunicazione PHP - SQL


Per i file:

$filename=”foo”

$contents=file_get_contents($filename,$text);
if($contents===false)
throw new Exception(“Error”);
var_dump($contents);

$filename=”foo”
$text=”This is a text”

$bites=file_put_contents($filename,$text);
if($bytes===false)
throw new Exception(“Error”);
printf(“%d bytes written in %s\n”,$bytes,$filename);

—————————————————————————————————————————

Useremo l’API “PDO”.

PDO
PHP Data Object, implementato da PHP7. Prima di PDO c’erano le MySQL functions che
servivano per connettersi solo a server MySQL e sono ormai deprecate. Successivamente
c’è stata l’API MySQLi, estensione di MySQL functions ma utilizzabile sia in modo
procedurale che ad oggetti.

Funziona per qualsiasi database e funziona ad oggetti. Fornisce un livello di astrazione


proprio perché può essere usato con qualsiasi database.

Connessione
$db_host = “localhost”; // dove sta il server
$db_user = “pippo”; // l’utente utilizzato
$db_password = “”; // la password dell’utente, è opzionale
$db_name = “nome_database”; // il nome del database su cui voglio lavorare

try {
// connessione
$connessione = new PDO(“mysql:host=$db_host;dbname=$db_name”, $db_user,
$db_password);

// QUI POSSO FARE LE MIE OPERAZIONI

// impostazione dell’attributo per gli errori


$connessione ->setAttribute (PDO::ATTR_ERRMODE,
PDO::ERRMODE_EXCEPTION); // richiamo il metodo setAttribute dall’oggetto
$connessione
} catch (PDOException $e) {
// notifica in caso d’errore
die()
} finally {
// chiusura connessione
$connessione = null;
}
// non è obbligatorio usare un blocco try catch

PDO::ATTR_ERRMODE può essere impostato in 3 modi:

● PDO::ERRMODE_SILENT (Default): gli errori sono silenziosi e quindi non vengono


generati errori.
● PDO::ERRMODE_WARNING: gli errori sono registrati in WARNING ma comunque il
programma non è interrotto.
● PDO::ERRMODE_EXCEPTION: gli errori sono mostrati e il programma smette di
funzionare.

Estrazione di dati
$sql = “SELECT nome, cognome FROM contatti”;
$pdo_stmt = $connessione->query($sql); // mi restituisce la tabella della query
foreach ($pdo_stmt as $row) {
echo $row[‘nome’].“ ”.$row[‘cognome].”<br/>”; // posso recuperarlo sia in modo
associativo che in maniera indicativa (0,1,2…)

Il metodo quote() serve a trasformare i caratteri speciali in codice ASCII o Unicode, così che
non danno fastidio al mio database.

Il metodo query() serve per le operazioni di lettura (Read). E restituisce un array associativo
contenente le informazioni che ho chiesto. Questo array è sia indicizzato che associativo.

Il metodo exec() serve a fare operazioni di CUD (Create Update Delete) e restituisce il
numero di linee modificate/coinvolte nell’operazione, oppure restituisce “false” se
l’operazione non è andata a buon fine. NB si usa spesso in combinazione con il metodo die()
confrontando prima se non sono state effettuate modifiche ($aggiorna_dati === FALSE).

Quando vogliamo inserire i dati, è meglio iniziare una transazione con il metodo
startTransaction(). Si fanno tutte le operazioni e solo alla fine commit(). Nel caso in cui
qualcosa va male, c’è il metodo rollback() per tornare indietro.

Solitamente i dati del database sono inseriti in un file a parte con estensione “.php” alla fine,
in modo da non dover modificare il codice in caso di una migrazione o altri motivi.

Per qualsiasi operazione, possiamo sempre usare i metodi prepare() e execute() per
eseguire, quindi al posto di exec. Li usiamo quando dobbiamo inserire nel database dei dati
che sono stati messi dal client. Oppure quando si vuole effettuare una query con un
“WHERE”. Con il metodo bindValue() fa un aggancio per valore, mentre con bindParam()
per segnaposto.

03/04/2023

Esercitazione Query
SELECT S.idstudente, S.cognome, S.nome, V.voto
FROM Studenti S
INNER JOIN Voti V
ON V.idstudente = S.idstudente Se la chiave primaria e la chiave esterna
hanno lo stesso nome, puoi sostituire con “USING(nomeAttributo)”
INNER JOIN Materie M
ON M.idmateria = V.idmateria
WHERE M.descrizione = “Matematica”

SELECT DISTINCT cognome, nome, classe


FROM Studenti S
INNER JOIN Voti V
ON V.idstudente = S.idstudente
INNER JOIN Materie M
ON M.idmateria = V.idmateria
WHERE M.descrizione = “DESCRIZIONE_DATA”
AND V.voto < 5

SELECT cognome, nome, COUNT(voto)


FROM Studenti S
INNER JOIN Voti V
ON V.idstudente = S.idstudente
INNER JOIN Materie M
ON M.idmateria = V.idmateria
WHERE V.voto > 5
AND M.descrizione = “Italiano”
GROUP BY cognome, nome
ORDER BY cognome, nome ASC

SELECT M.idmateria, M.descrizione, COUNT(iddocente) Se ho una funzione di


aggregazione e attributi semplici, devo per forza avere un GROUP BY
FROM Materie M
INNER JOIN Docenti D
ON D.idmateria = M.idmateria
GROUP BY M.idmateria
Outer join
L’inner join è l’intersezione di 2 tabelle dove corrisponde un campo. Poi ci sono le outer join,
che prendono in considerazione anche tuple senza corrispondenza.

Ci sono 3 tipi di outer join:

Left Join
Sono completate con “null” le tuple dell’operando di sinistra.

FROM Tabella1 A < Sinistra


LEFT JOIN Tabella2 B < Destra
ON A.Key = B.Key

Se una tupla di A non è legata a nessun valore di B, viene completata con “null”.

Right Join
Sono completate con “null” le tuple dell’operando di destra.

Sono completate con “null” le tuple dell’operando di sinistra.

FROM Tabella1 A < Sinistra


LEFT JOIN Tabella2 B < Destra
ON A.Key = B.Key

Se una tupla di B non è legata a nessun valore di A, viene completata con “null”.

Normalizzazione
Consiste nell’insieme dei criteri di progettazione di un DB relazionale per prevenire le
anomalie. Un’anomalia in inserimento accade quando devo inserire informazioni già
inserite, un’anomalia di cancellazione accade quando devo cancellare informazioni che
sono ancora utili, un’anomalia di aggiornamento accade quando devo cambiare
un’informazione già cambiata.

Una tabella è in prima forma normale quando ogni attributo contiene solo un’informazione
quindi essere semplici (si dicono atomici).

Una tabella è in seconda forma normale quando comprende le precedenti forme normali e
quando tutti gli attributi dipendono dall’intera chiave e non solo da una parte (quindi solo se
la chiave primaria è composta). Non ho assolutamente capito, proprio ZERO. Però tu devi
avere solo una chiave primaria ed eventualmente creare una nuova tabella in cui il campo
che non dipendeva da tutte le chiavi è campo e la chiave da cui il campo dipendeva è la
chiave.
Una tabella è in terza forma normale quando comprende le precedenti forme normali e ci
sono attributi che dipendono dalla chiave in modo transitivo. Ovvero l’attributo non chiave
dipende da un altro attributo non chiave.

08/05/2023

Esempio
CM Materia CS Sem. CD NomeDoc Dipartimento

I01 Analisi I Inf I NR1 Neri Matematica

I01 Analisi I El I NR2 Neri Matematica

I02 Analisi II El-Inf I NR1 Neri Matematica

I04 Fisica I El II BN1 Bianchi Fisica

I04 Fisica I Mec I BR1 Bruni Meccanica

I04 Fisica I Inf I BR1 Bruni Meccanica

I05 Fisica II El II BR1 Bruni Meccanica

I06 Chimica Tutti I RS1 Rossi Fisica

La tabella non è in prima forma normale poiché non è presente una chiave primaria. Si
prendono come chiavi primarie gli attributi CM, CS e CD poiché sono le 3 entità individuate.

Prima forma normale

CM Materia CS Sem. CD NomeDoc Dipartimento

I01 Analisi I Inf I NR1 Neri Matematica

I01 Analisi I El I NR2 Neri Matematica

I02 Analisi II El-Inf I NR1 Neri Matematica

I04 Fisica I El II BN1 Bianchi Fisica

I04 Fisica I Mec I BR1 Bruni Meccanica

I04 Fisica I Inf I BR1 Bruni Meccanica

I05 Fisica II El II BR1 Bruni Meccanica

I06 Chimica Tutti I RS1 Rossi Fisica

La tabella non è in seconda forma normale siccome non tutti gli attributi non chiave
dipendono dall’intera chiave.
● Anomalia all’inserimento: Se si vuole inserire una nuova materia, si devono
aggiungere anche tutte le informazioni del corso di studio e del docente.
● Anomalia in aggiornamento: Per aggiornare le informazioni di un professore, si
devono modificare più di 1 tupla.
● Anomalia all’eliminazione: Se si deve eliminare un docente, si perdono anche le
informazioni della materia e del corso.
Seconda forma normale

CS Sem. CS CM CS CD

Inf I Inf I01 Inf NR1

El I El I01 El NR2

El-Inf I El-Inf I02 El-Inf NR1

El II El I04 El BN1

Mec I Mec I04 Mec BR1

Inf I Inf I04 Inf BR1

El II El I05 El BR1

Tutti I Tutti I06 Tutti RS1

CM Materia CD NomeDoc Dipartimento

I01 Analisi I NR1 Neri Matematica

I01 Analisi I NR2 Neri Matematica

I02 Analisi II NR1 Neri Matematica

I04 Fisica I BN1 Bianchi Fisica

I04 Fisica I BR1 Bruni Meccanica

I04 Fisica I BR1 Bruni Meccanica

I05 Fisica II BR1 Bruni Meccanica

I06 Chimica RS1 Rossi Fisica


Terza forma normale

CS Sem. CM CD

Inf I I01 NR1

El I I01 NR2

El-Inf I I02 NR1

El II I04 BN1

Mec I I04 BR1

Inf I I04 BR1

El II I05 BR1

Tutti I I06 RS1

CD NomeDoc Dipartimento

NR1 Neri Matematica

NR2 Neri Matematica

NR1 Neri Matematica

BN1 Bianchi Fisica

BR1 Bruni Meccanica

BR1 Bruni Meccanica

BR1 Bruni Meccanica

RS1 Rossi Fisica

27/04/2023

Correzione prova esame


SCHEMA LOGICO

Cliente (id_Cliente, Denominazione, ecc…)

Impianto (id_Impianto, Denominazione, Indirizzo, Longitudine, Latitudine, id_Cliente)

Controllore (id_Controllore, Marca, Modello, id_Impianto)

Montato (id_Impianto, id_Trasduttore)


Trasduttore (id_Trasduttore, ecc…)

Tecnico(id_Tecnico, ecc…)

Intervento (id_Intervento, dataOraEsecuzione, dataOraProgrammata, dataOraFine, Esito,


id_Impianto, id_Tecnico)

28/04/2023

Subqueries
Step 1

SELECT att_attore.CodiceAttore
FROM att_attore
WHERE att_attore.Cognome = “Pitt”
OR att_attore.Cognome = “Clooney”

Step 2

SELECT att_film.Titolo
FROM att_film
INNER JOIN att_interpreta
ON att_film.CodiceFilm = att_interpreta.CodiceFilm
WHERE att_interpreta.Codiceattore in (
SELECT att_attore.CodiceAttore
FROM att_attore
WHERE att_attore.Cognome = “Pitt”
OR att_attore.Cognome = “Clooney”
)
GROUP BY att_film.Titolo
HAVING COUNT(*) = 2
Step 1

SELECT att_programmato.CodiceFilm
FROM att_programmato
INNER JOIN att_cinema
ON att_cinema.CodiceCinema = att_programmato.CodiceCinema
WHERE att_cinema.Citta = “Bologna”

Step 2

SELECT att_film.Titolo
FROM att_film
WHERE att_film.CodiceFilm not in (
SELECT att_programmato.CodiceFilm
FROM att_programmato
INNER JOIN att_cinema
ON att_cinema.CodiceCinema = att_programmato.CodiceCinema
WHERE att_cinema.Citta = “Bologna”
)

—-------------------------------------------------------------------------------------------------------------

Step 1

SELECT att_programmato.CodiceFilm
FROM att_programmato
INNER JOIN att_cinema
ON att_cinema.CodiceCinema = att_programmato.CodiceCinema
WHERE att_cinema.Citta != “Bologna”

Step 2

SELECT att_film.Titolo
FROM att_film
WHERE att_film.CodiceFilm not in (
SELECT att_programmato.CodiceFilm
FROM att_programmato
INNER JOIN att_cinema
ON att_cinema.CodiceCinema = att_programmato.CodiceCinema
WHERE att_cinema.Citta != “Bologna”
)

—---------------------------------------------------------------------------------------------------------

Potrebbero piacerti anche