-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
253 additions
and
112 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# Dipendenze funzionali | ||
|
||
Dato uno schema $R(T, F)$, sono detti **dipendenze funzionali** quei vincoli: | ||
$$ | ||
X \rightarrow Y \in F | ||
$$ | ||
dove $X \cup Y \subseteq T$, per cui l'unicità di $Y$ dipende da $X$. | ||
|
||
Sono anche dette **derivate** se $F$ le **implica logicamente**, cioè: | ||
$$ | ||
F \models X \rightarrow Y \Leftrightarrow F \vdash X \rightarrow Y | ||
$$ | ||
che accade sse ogni istanza $r$ **soddisfa** $X \rightarrow Y$, ovvero: | ||
$$ | ||
\forall t, u \in r,\ t.X = u.X \Rightarrow t.Y = u.Y | ||
$$ | ||
|
||
## Assiomi | ||
|
||
La **derivazione** di altre _dipendenze_ da $F$ avviene sfruttando gli **assiomi di Armstrong**: | ||
- **Riflessività**, $Y \subseteq X \Rightarrow X \rightarrow Y$ | ||
- **Aumento**, $X \rightarrow Y \Rightarrow XW \rightarrow YW$ | ||
- **Transitività**, $X \rightarrow Y \land Y \rightarrow Z \Rightarrow X \rightarrow Z$ | ||
|
||
da cui si possono ricavare le **regole derivate** di: | ||
- **Unione**, $X \rightarrow Y \land X \rightarrow Z \Rightarrow X \rightarrow YZ$ | ||
- **Decomposizione**, $X \rightarrow YZ \Rightarrow X \rightarrow Y$ | ||
- **Indebolimento**, $X \rightarrow Y \Rightarrow XZ \rightarrow Y$ | ||
|
||
## Chiusura | ||
|
||
Si dice **chiusura** di $F$, l'insieme di tutte le dipendenze derivabili da $F$: | ||
$$ | ||
F^+ = \Set{X \rightarrow Y | F \vdash X \rightarrow Y} | ||
$$ | ||
che però risulta essere algoritmicamente **inefficiente** da trovare. | ||
|
||
La **chiusura** di un attributo $X \subseteq T$ invece, è l'insieme degli attributi la cui dipendenza per $X$ è _derivabile_: | ||
$$ | ||
X_F^+ = \Set{A \in T | F \vdash X \rightarrow A} | ||
$$ | ||
e semplifica la risoluzione del **problema dell'implicazione**, cioè la verifica che $X \rightarrow Y \in F^+$, perchè: | ||
$$ | ||
F \vdash X \rightarrow Y\ \Leftrightarrow\ Y \subseteq X_F^+ | ||
$$ | ||
|
||
Trovare la _chiusura_ di $X$ consiste quindi nel cominciare con $X^+ = X$ e aggiungerci iterativamente gli attributi che dipendono da quelli dentro $X^+$. | ||
|
||
### Algoritmo | ||
|
||
Trovare la _chiusura_ $X_F^+$ di un insieme di attributi $X$ consiste nel: | ||
1. Iniziare con l'insieme $Z = X$ | ||
2. Trovare tutte le dipendenze $W \rightarrow Y \in F$ per cui $W \subseteq Z$ | ||
3. Aggiungere a $Z$ gli attributi $Y$ delle dipendenze trovate | ||
4. Ripetere finchè $Z$ viene aggiornato | ||
|
||
Per esempio, se $X = AB$ e $F = \{A \rightarrow C, AC \rightarrow D, E \rightarrow F\}$ allora $Z_1 = ABC$ e $Z_2 = ABCD$. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# Chiavi | ||
|
||
Degli attributi $X$ di $R(T, F)$ si possono definire come: | ||
- **Superchiave** quando $X_F^+ = T$ | ||
- **Chiave** quando $X$ è _superchiave_ e $\forall A \in X,\ (X \setminus \{A\})_F^+ \neq T$ | ||
- **Attributi primi** se ognuno appartiene ad almeno una _chiave_ | ||
|
||
### Algoritmo | ||
|
||
Dato il **candidato** $X :: (Y)$, la cui $X$ è una **possibile chiave** mentre $Y$ sono i possibili attributi da aggiungere se non lo fosse, si possono trovare **tutte le chiavi** di $R(T, F)$ attraverso: | ||
1. Iniziare con il candidato $Z :: (T \setminus Z)$, dove $Z = T \setminus \Set{Y | X \rightarrow Y \in F}$ sono attributi indipendenti | ||
2. Estrarre il primo candidato $X :: (Y)$ assicurandosi che $X$ non contenga alcuna chiave già trovata | ||
- Se $X$ è _superchiave_ si può aggiungere alle chiavi trovate | ||
- Altrimenti ai candidati si unisce $\Set{XA :: (W \setminus \{A\}) | A \in W}$, dove $W = Y \setminus X_F^+$ | ||
3. Ripetere finchè rimangono candidati validi | ||
|
||
Serve anche a **verificare la primalità** degli attributi, dato che altrimenti il processo è molto **inefficiente**. | ||
|
||
#### Esempio | ||
|
||
Per esempio, se $T = ABCDEF$ e $G = \{AB \rightarrow C, E \rightarrow A, A \rightarrow E, B \rightarrow F\}$ i passaggi sono: | ||
1. Il candidato iniziale è $BD :: (ACEF)$ | ||
2. $BD$ non è _superchiave_ quindi si aggiungono i candidati dagli attributi $ACEF \setminus BDF$ | ||
3. Il primo candidato $BDA :: (CE)$ tra i rimanenti è valido | ||
4. $BDA$ è _superchiave_ quindi anche **chiave** | ||
5. Il primo candidato $BDC :: (E)$ è valido | ||
6. $BDC$ non è _superchiave_ quindi si aggiungono i candidati | ||
7. Il primo candidato $BDE :: ()$ è valido | ||
8. $BDE$ è _superchiave_ quindi anche **chiave** | ||
9. Il rimanente candidato $BDCE$ contiene la chiave $BDE$ quindi non è valido |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# Forma e copertura canonica | ||
|
||
Le _dipendenze funzionali_ $F$ sono dette **in forma canonica** sse per ogni $X \rightarrow Y \in F$: | ||
- $|Y| = 1$ | ||
- $X$ non ha attributi **estranei**, cioè $\nexists A \in X : X \setminus \{A\} \rightarrow Y \in F^+$ | ||
- $X \rightarrow Y$ non è **ridondante**, cioè $X \rightarrow Y \not\in (F \setminus \{X \rightarrow Y\})^+$ | ||
|
||
Se $G$ è in _forma canonica_ e $F \equiv G$, ovvero **equivalgono** per $F^+ = G^+$, allora è detta **copertura canonica**. | ||
|
||
### Algoritmo | ||
|
||
Trovare la _copertura canonica_ di $F$ consiste nel: | ||
1. Iniziare con l'insieme di dipendenze _decomposte_ $G = \Set{X \rightarrow A | X \rightarrow Y \in F \land A \in Y}$ | ||
2. Rimpiazzare da $G$ le $X \rightarrow A$ per cui $|X| > 1$, con $Z \rightarrow A$ dove $Z$ è $X$ meno gli attributi _estranei_, rimuovendo un $B \in X$ alla volta e verificando che comunque $A \in (Z \setminus \{B\})_G^+$ | ||
3. Rimuovere le $X \rightarrow A$ _ridondanti_, verificando che $A \in X_{G \setminus \{X \rightarrow A\}}^+$ | ||
|
||
#### Esempio | ||
|
||
Per esempio, se $F = \{A \rightarrow BC, B \rightarrow C, A \rightarrow B, AB \rightarrow C\}$: | ||
1. Decomponendo si ottiene $G = \{A \rightarrow C, B \rightarrow C, A \rightarrow B, AB \rightarrow C\}$ | ||
2. Si rimpiazza $AB \rightarrow C$ con $B \rightarrow C$ perchè $C \in B_G^+ = BC$ finendo senza poter rimuovere $B$ | ||
3. Si rimuove $A \rightarrow C$ perchè $C \in A_{\{B \rightarrow C, A \rightarrow B\}}^+ = ABC$ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
# Decomposizione di schemi | ||
|
||
Le [anomalie](../README.md) possono essere risolte attraverso la **decomposizione** dello schema in schemi **più piccoli**. | ||
|
||
Dato uno schema $R(T, F)$, si definisce come **proiezione** di $F$ su $Z \subseteq T$ l'insieme: | ||
$$ | ||
\pi_Z(F) = \Set{X \rightarrow Y \in F^+ | X \cup Y \subseteq Z} | ||
$$ | ||
attraverso cui si trova una **decomposizione** di $R(T, F)$, cioè un insieme di schemi | ||
$$ | ||
\rho = \{R_1(T_1, F_1), ..., R_n(T_n, F_n)\} | ||
$$ | ||
per cui $\bigcup_i T_i = T$ e $F_i = \pi_{T_i}(F)$ filtrando per ogni $R_i$ le dipendenze con attributi coinvolti in $T_i \neq \emptyset$. | ||
|
||
Per esempio su $R(ABCDE, \{AB \rightarrow CD, B \rightarrow E\})$ si risolvono le anomalie decomponendolo in: | ||
- $R_1(ABCD, \{AB \rightarrow CD\})$ | ||
- $R_2(BE, \{B \rightarrow E\})$ | ||
|
||
### Algoritmo | ||
|
||
Il calcolo della _proiezione_ $\pi_{T_i}(F)$ avviene dal: | ||
1. Iniziare con l'insieme $P = \emptyset$ | ||
2. Per ogni $X \subset T_i$ trovare $Y = X_F^+ \setminus X$ | ||
3. Aggiungere a $P$ la dipendenza $X \rightarrow (Y \cap T_i)$ | ||
|
||
#### Esempio | ||
|
||
Per esempio su $\pi_{AB}(\{A \rightarrow B, B \rightarrow C, C \rightarrow A\})$, si ha: | ||
1. L'insieme delle proiezioni iniziale è $P = \emptyset$ | ||
2. Si trovano le $X \subset AB$ da usare dall'[insieme delle parti](../../../ct0434/02/README.md#insiemi-delle-parti) di $AB$ | ||
3. Per $X = A$ si trova $Y = A_F^+ \setminus A = BC$ | ||
4. A $P$ si aggiunge $A \rightarrow (BC \cap AB) = A \rightarrow B$ | ||
5. Per $X = B$ si trova $Y = B_F^+ \setminus B = AC$ | ||
6. A $P$ si aggiunge $B \rightarrow (AC \cap AB) = B \rightarrow A$ | ||
|
||
## Preservazione dei dati | ||
|
||
Per dire che la _decomposizione_ **preservi i dati**, si deve avere che: | ||
$$ | ||
r = \pi_{T_1}(r) \bowtie ... \bowtie \pi_{T_n}(r) | ||
$$ | ||
per ogni istanza $r$ di $R(T, F)$, assicurandosi che dalle tabelle decomposte si **ricavino gli stessi dati** di $r$. | ||
|
||
Per **verificare** che una decomposizione $\rho = \{R_1(T_1, F_1), R_2(T_2, F_2)\}$ _preservi i dati_ basta verificare che | ||
$$ | ||
T_1 \cap T_2 \rightarrow T_1 \in F^+ \lor\ T_1 \cap T_2 \rightarrow T_2 \in F^+ | ||
$$ | ||
trovando la [chiusura](../01/README.md#algoritmo) $(T_1 \cap T_2)_F^+$ e verificando che contenga $T_1$ o $T_2$. | ||
|
||
Per esempio, con $R(ABCD, \{A \rightarrow BC\})$ si trova $T_1 = ABC$, $T_2 = AD$ e $A_F^+ = ABC = T_1$. | ||
|
||
## Preservazione delle dipendenze | ||
|
||
Per dire che la _decomposizione_ **preservi le dipendenze**, si deve avere che: | ||
$$ | ||
G = \bigcup_i \pi_{T_i}(F) \equiv F | ||
$$ | ||
|
||
### Algoritmo | ||
|
||
Per **verificare** che le dipendenze siano _preservate_ basta assicurarsi che $Y \subseteq X_G^+$, per ogni $X \rightarrow Y \in F$. | ||
|
||
Mentre $X_G^+ = X_{\bigcup_i \pi_{T_i}(F)}^+$ si può ricavare con: | ||
1. Iniziare con l'insieme $Z = X$ | ||
2. Trovare tutti gli schemi $R_i(T_i, F_i) \in \rho$ | ||
3. Aggiungere a $Z$ gli attributi $(Z \cap T_i)_F^+ \cap T_i$ | ||
4. Ripetere finchè $Z$ viene aggiornato | ||
|
||
#### Esempio | ||
|
||
Per esempio se $F = \{A \rightarrow B, B \rightarrow C, C \rightarrow A\}$ e $\rho = \{R_1(AB), R_2(BC)\}$, si ha: | ||
1. Verifica che $B \subseteq A_G^+$ | ||
1. L'insieme iniziale è $Z = A$ e il primo schema è $R_1(AB)$ | ||
2. A $Z$ si aggiunge $(Z \cap T_1)_F^+ \cap T_1 = (A \cap AB)_F^+ \cap AB = ABC \cap AB = AB$ | ||
3. Il prossimo schema è $R_2(BC)$ | ||
4. A $Z$ si aggiunge $(Z \cap T_2)_F^+ \cap T_2 = (AB \cap BC)_F^+ \cap BC = ABC \cap BC = BC$ | ||
5. Quindi è verificato perchè $B \subseteq Z = ABC$ | ||
2. Verifica che $C \subseteq B_G^+$ | ||
1. L'insieme iniziale è $Z = B$ e il primo schema è $R_1(AB)$ | ||
2. A $Z$ si aggiunge $B_F^+ \cap AB = AB$ | ||
3. Il prossimo schema è $R_2(BC)$ | ||
4. A $Z$ si aggiunge $B_F^+ \cap BC = BC$ | ||
5. Quindi è verificato perchè $C \subseteq Z = ABC$ | ||
3. Verifica che $A \subseteq C_G^+$ | ||
1. L'insieme iniziale è $Z = C$ e il primo schema è $R_1(AB)$ | ||
2. A $Z$ si aggiunge $\emptyset_F^+ \cap AB = \emptyset$ | ||
3. Il prossimo schema è $R_2(BC)$ | ||
4. A $Z$ si aggiunge $C_F^+ \cap BC = BC$ | ||
5. Il prossimo schema è $R_1(AB)$ di nuovo | ||
6. A $Z$ si aggiunge $B_F^+ \cap AB = AB$ | ||
7. Quindi è verificato perchè $A \subseteq Z = ABC$ | ||
|
||
## Relazione tra dati e dipendenze | ||
|
||
Data una _decomposizione_ $p = \{R_1(T_1), ..., R_n(T_n)\}$ di $R(T, F)$ che **preserva le dipendenze** e per cui esiste un $T_i$ _superchiave_ di $R$ allora $p$ si dice che **preserva anche i dati**. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# Forme normali | ||
|
||
Le **forme normali** si possono ottenere attraverso il processo di **normalizzazione**, che coinvolge la [decomposizione](../04/README.md), e che garantisce la qualità dello schema risultante. | ||
|
||
## Forma normale di Boyce-Codd | ||
|
||
Uno schema $R(T, F)$ è in **BCNF** sse per ogni $X \rightarrow Y \in F$ tale che $Y \nsubseteq X$ si ha che $X$ è una _superchiave_. | ||
|
||
Questa forma **preserva i dati**, garantisce l'**assenza di anomalie** ma **non preserva le dipendenze**. | ||
|
||
### Algoritmo di analisi | ||
|
||
La conversione in _BCNF_ consiste nel _decomporre_ **ricorsivamente** lo schema $R(T, F)$: | ||
1. Per il caso base, se $R(T, F)$ è in _BCNF_ restituire $\{R(T, F)\}$ | ||
2. Altrimenti trovare una $X \rightarrow Y \in F$ che viola la _BCNF_ | ||
3. Calcolare gli attributi $T_1 = X_F^+$ e $T_2 = X \cup (T \setminus T_1)$ | ||
4. Calcolare le proiezioni $F_1 = \pi_{T_1}(F)$ e $F_2 = \pi_{T_2}(F)$ | ||
5. Trovare la decomposizione _ricorsiva_ $\rho_1$ di $R_1(T_1, F_1)$ e $\rho_2$ di $R_2(T_2, F_2)$ | ||
6. Restituire $\rho_1 \cup \rho_2$ | ||
|
||
#### Esempio | ||
|
||
Per esempio con $R(ABC, \{AB \rightarrow C, C \rightarrow A\})$ la conversione sarebbe: | ||
1. La _BCNF_ è violata da $C \rightarrow A$ perchè $C$ non è _superchiave_, infatti $C_F^+ \neq ABC$ | ||
2. Si calcolano $T_1 = C_F^+ = AC$ e $T_2 = BC$ | ||
3. Si calcolano $F_1 = \{C \rightarrow A\}$ e $F_2 = \emptyset$ | ||
4. Si trovano le decomposizioni $\rho_1 = \{R_1(AC, \{C \rightarrow A\})\}$ e $\rho_2 = \{R_2(BC, \emptyset)\}$ | ||
|
||
## Terza forma normale | ||
|
||
Uno schema $R(T, F)$ è detto in **3NF** sse per ogni $X \rightarrow Y \in F$ tale che $Y \nsubseteq X$ si ha che $X$ è una _superchiave_ oppure tutti gli attributi $Y \setminus X$ sono _attributi primi_. | ||
|
||
Conviene quindi prima [trovare le chiavi](../02/README.md#algoritmo) di $R$ e poi verificarne la proprietà. | ||
|
||
Questa forma **preserva i dati e le dipendenze**, ma può comunque possedere **anomalie**. | ||
|
||
### Algoritmo di sintesi | ||
|
||
La conversione in _3NF_ consiste nel: | ||
1. Iniziare con la _copertura canonica_ $G$ di $F$ | ||
2. Rimpiazzare da $G$ le $X \rightarrow A_1, ..., X \rightarrow A_n$ con una singola $X \rightarrow A_1, ..., A_n$ | ||
3. Creare un $R_i(XY)$ per ogni $X \rightarrow Y \in G$ | ||
4. Rimuovere gli schemi i cui attributi fanno parte di un altro schema più grande | ||
5. Se nessun $R_i$ ha attributi _superchiave_ per $R$, aggiungere un $R_{n+1}(Z)$, dove $Z$ è una chiave di $R$ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters