Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Dati due insiemi D1 e D2, non necessariamente disgiunti, una relazione R definita su D1 e D2
è un qualunque sottoinsieme del prodotto cartesiano.
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.
Di una tabella è definito grado di una tabella il numero delle colonne (degli attributi). Mentre
è definita cardinalità il numero delle righe (dei record).
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.
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).
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 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).
Metodo 1
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.
Corso (Codice, Numero, Id (La chiave primaria dell’entità a 1, migra su quella con entità a N)
Frequenta (Codice, Matricola) (Perché è una relazione N a N, formano una nuova tabella, gli
attributi sono chiavi esterne ed insieme formano la chiave primaria)
30/01/2023
Schema E/R
Abbonamento
Ha id_abbonamento, data e periodo (trimestrale, semestrale o annuale). id_abbonamento è
la chiave primaria.
Pubblicazione
Ha id_pubblicazione, titolo, prezzo, periodicita. id_pubblicazione è la chiave primaria.
Articolo
Ha id_articolo, titolo e testo. id_articolo è la chiave primaria.
Abbonato
Ha id_abbonato e tutta l’anagrafica. id_abbonato è la chiave primaria.
Argomento
Ha id_argomento e nome. id_argomento è la chiave primaria.
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)
Tratta(id_pubb, id_argomento)
06/02/2023
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).
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.
Il primo comando è:
07/02/2023
SQL però non permette di usare CHECK in questo modo. Al suo posto, si usa ENUM che
corrisponde solo a IN.
13/02/2023
ALTER:
DROP:
DML
UPDATE:
UPDATE nome_tabella
SET campo1 = valore1
campo2 = valore2
…
WHERE condizione;
DELETE:
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 (π).
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.
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.
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
Funzioni di raggruppamento
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
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
20/03/2023
Esempi di query
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”)
a. SELECT COUNT(*)
FROM Sale
WHERE Posti > 60 AND Citta = “Pisa”
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
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).
9. Il numero di attori dei film in cui appaiono solo attori nati prima del 1970
$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);
—————————————————————————————————————————
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.
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);
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”
Left Join
Sono completate con “null” le tuple dell’operando di sinistra.
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.
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
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.
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
El I El I01 El NR2
El II El I04 El BN1
El II El I05 El BR1
CS Sem. CM CD
El I I01 NR2
El II I04 BN1
El II I05 BR1
CD NomeDoc Dipartimento
27/04/2023
Tecnico(id_Tecnico, ecc…)
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”
)
—---------------------------------------------------------------------------------------------------------