Avanti Indietro Indice

Traduzione del modello ER nel modello relazionale

Esistono delle regole per tradurre uno schema ER in uno schema relazionale equivalente, cioè che rappresenta la stessa informazione. Questa traduzione si muove dall'astratto al concreto. Il risultato della traduzione è quindi un passo più lontano dal livello concettuale e un passo più vicino al livello fisico dei dati. In particolare, il risultato è organizzato secondo il modello dei dati che è stato scelto (il modello relazionale nel nostro caso).

Prima di iniziare la traduzione occorre notare che, mentre gli attributi del modello relazionale assumono solo valori atomici, il modello ER permette di specificare attributi composti (che assumono una sequenza di valori non omogenei) e attributi multivalore (che assumono una sequenza di valori omogenei). Occorre dunque rimuovere questi attributi mediante una fase preliminare di ristrutturazione del modello ER.

La rimozione degli attributi composti è semplice. Essi vengono sostituiti con gli attributi componenti come nel seguente caso:

plot/er13.png

Eventuali gerarchie di attributi composti si traducono similmente procedendo dalle foglie verso la radice. A questo punto tutti gli attributi sono semplici, derivati, oppure multivalore. Per rimuovere gli attributi multivalore si crea una nuova entità che contiene i valori dell'attributo e la si collega all'entità che possedeva l'attributo mediante una nuova relazione uno a molti o molti a molti, a seconda dei casi. Segue un esempio:

plot/er14.png

Se l'attributo telefono è opzionale, il vincolo di cardinalità (1,1) va sostituito con (0,1). Se inoltre un numero di telefono può essere condiviso da più persone (ad esempio, il telefono di casa), allora il vincolo di cardinalità (1,1) va sostituito con (0,N).

Vediamo ora quali sono le regole di traduzione assumendo che non ci siano attributi composti o multivalore. Ogni regola si applica ad un frammento di schema ER ed ha come risultato un insieme di schemi di relazione corrispondenti al frammento ER in ingresso.

Entità
Una entità viene tradotta in una relazione con lo stesso nome, gli stessi attributi e la stessa chiave dell'entità. Segue un esempio di traduzione:
plot/er15.png

dipendente(codiceFiscale, nome, cognome, dataDiNascita, età)

Per gli attributi calcolati va aggiunto un vincolo di integrità che specifica il metodo di calcolo. Nel caso di età, il vincolo afferma che il valore di tale attributo si ottiene come differenza tra la data odierna e la data di nascita di una persona, se tale informazione esiste, altrimenti il suo valore è nullo.
Relazione molti a molti
Una relazione molti a molti tra due entità si traduce con una relazione con lo stesso nome avente come attributi le chiavi delle entità coinvolte, che formano la chiave della relazione, più eventuali attributi della relazione. Gli attributi possono eventualmente essere rinominati per maggiore chiarezza. Segue un esempio di traduzione:
plot/er16.png

dipendente(codiceFiscale)

teatro(nome)

lavoro(dipendente, teatro, dataDiAssunzione, ruolo)

lavoro(teatro) --> teatro(nome)

lavoro(dipendente) --> dipendente(codiceFiscale)

Nello schema di relazione lavoro abbiamo rinominato l'attributo codice fiscale di dipendente con dipendente e l'attributo nome di teatro con teatro. Esistono inoltre vincoli di chiave esterna tra l'attributo dipendente della relazione lavoro e la relazione dipendente e tra l'attributo teatro della relazione lavoro e la relazione teatro. La traduzione mostrata rimane valida anche nel caso di cardinalità minima diversa da 1, e in particolare quando essa vale 0.

Similmente si traducono le relazioni binarie ricorsive di tipo molti a molti. In tal caso la rinominazione degli attributi è essenziale al fine di evitare attributi con lo stesso nome nello stesso schema di relazione:
plot/er17.png

nodo(nome)

arco(predecessore, successore, peso)

arco(predecessore) --> nodo(nome)

arco(successore) --> nodo(nome)

Le relazioni con più di due entità partecipanti di tipo molti a molti si traducono in modo analogo. Segue un esempio di traduzione:
plot/er18.png

fornitore(partitaIVA)

dipartimento(nome)

prodotto(codice)

fornitura(fornitore, dipartimento, prodotto, quantità)

fornitura(fornitore) --> fornitore(partitaIVA)

fornitura(dipartimento) --> dipartimento(nome)

fornitura(prodotto) --> prodotto(codice)

Relazione uno a molti
Trattiamo solo il caso binario. Il caso con più di due relazioni di tipo uno a molti è raro e comunque traducibile in modo simile. In questo caso uno dei due vincoli di cardinalità è di tipo (1,1) oppure (0,1), mentre l'altro vincolo è di tipo (k,N), con k un naturale fissato. Se il primo vincolo di cardinalità è di tipo (1,1) la traduzione rappresenta la relazione concettuale sfruttando l'entità che partecipa alla relazione con cardinalità massima pari a uno. Segue un esempio:
plot/er19.png

teatro(nome)

stagione(nome, biennio, teatro)

stagione(teatro) --> teatro(nome)

Si noti che in questo caso l'attributo teatro di stagione non assume mai valori nulli in quanto ogni stagione ha esattamente un teatro associato.

Supponiamo che una stagione teatrale possa non avere ancora un teatro associato e dunque partecipi alla relazione offerta con vincolo di cardinalità (0,1):
plot/er22.png
In tal caso abbiamo due possibili traduzioni. La prima è quella appena vista. La seconda, simile alla traduzione di una relazione molti a molti, è la seguente:

teatro(nome)

stagione(nome, biennio)

offerta(nomeStagione, biennioStagione, teatro)

offerta(nomeStagione, biennioStagione) --> stagione(nome, biennio)

offerta(teatro) --> teatro(nome)

Si noti una differenza rispetto alla traduzione molti a molti: la chiave della relazione offerta è la chiave dell'entità stagione (cioè l'entità che partecipa alla relazione con vincolo massimo pari a 1). Infatti, esiste al massimo un teatro associato ad una stagione.

La prima traduzione ha il vantaggio di creare una tabella in meno. D'altronde, essa ha come svantaggio di dover inserire valori nulli per l'attributo teatro di stagione per quelle stagioni che non hanno associato un teatro. Questi valori nulli sono invece esclusi nella seconda traduzione in quanto la relazione offerta registra solo le associazioni esistenti tra stagione e teatro. Un criterio di scelta tra le due traduzioni è la valutazione del rapporto tra istanze di stagione con un teatro e istanze di stagione. Se questo rapporto è significativo (cioè se il numero di valori nulli da inserire è scarso) allora è preferibile la prima traduzione, altrimenti è meglio la seconda.

Mostriamo ora la traduzione di una relazione binaria ricorsiva di tipo uno a molti:
plot/er21.png

persona(nome, padre)

persona(padre) --> persona(nome)

In realtà in questo caso l'espressione chiave esterna non è esattamente appropriata in quanto padre fa parte della stessa tabella a cui fa riferimento.
Entità debole
La traduzione per una entità debole è simile alla prima traduzione per relazioni uno a molti. Infatti una entità debole è identificata da una entità proprietario mediante una relazione a cui partecipa con vincolo (1,1). Occorre però aggiungere alla chiave parziale della relazione dell'entità debole la chiave dell'entità proprietario, in quanto solo in questo modo le istanze dell'entità debole possono essere identificate. Ad esempio:
plot/er20.png

spazio(nome)

spettacolo(data, ora, spazio)

spettacolo(spazio) --> spazio(nome)

Se abbiamo un cammino di entità deboli E1, E2,..., En, dove le prime n-1 entità del cammino sono deboli e l'ultima è il proprietario, allora dobbiamo fare attenzione ad applicare la regola di traduzione a partire dalla fine del cammino, cioè dalla coppia (En-1, En), per poi proseguire all'indietro. In questo modo è possibile specificare una chiave per ognuna delle entità deboli. Si noti che tutte le entità coinvolte devono essere distinte altrimenti avremo un ciclo di entità deboli e sarebbe impossibile l'identificazione di una chiave per le entità deboli conivolte nel ciclo. Vediamo un esempio che coinvolge più di una entità debole:
plot/er23.png

spazio(nome)

spettacolo(data, ora, spazio)

prenotazione(codice, data, ora, spazio)

spettacolo(spazio) --> spazio(nome)

prenotazione(data, ora) --> spettacolo(data, ora)

prenotazione(spazio) --> spazio(nome)

Relazione uno a uno
Trattiamo solo il caso binario. Il caso con più di due relazioni di tipo uno a uno è molto raro e comunque traducibile in modo analogo. Vi sono quattro casi a seconda delle cardinalità minime (0 o 1) delle due entità partecipanti. Supponiamo che la partecipazione delle entità alla relazione sia obbligatoria:
plot/er24.png
Abbiamo due possibulità equivalenti. La prima è questa:

stato(nome)

presidente(nome, stato)

presidente(stato) --> stato(nome)

La seconda possibilità è simmetrica:

presidente(nome)

stato(nome, presidente)

stato(presidente) --> presidente(nome)

Dato che la relazione presidenza è biunivoca, una terza possibilità è quella di usare una unica relazione (presidente o stato) che raggruppa tutti e tre i concetti del frammento ER. Questa soluzione è tecnicamente giusta ma metodologicamente sbagliata. Infatti, a livello concettuale, i concetti di stato e presidente sono stati separati (per qualche motivo) e tale separazione deve persistere anche a livello logico.

Supponiamo ora che la partecipazione di una delle entità alla relazione sia opzionale:
plot/er25.png
La traduzione da preferire è la seguente:

cittadino(nome)

stato(nome, presidente)

stato(presidente) --> cittadino(nome)

Questa traduzione ha il vantaggio che non vengono inseriti valori nulli nelle relazioni.

Supponiamo infine che la partecipazione di entrambe le entità alla relazione sia opzionale:
plot/er26.png
In questo caso abbiamo una terza possibilità:

cittadino(nome)

stato(nome)

presidenza(stato, presidente)

presidenza(stato) --> stato(nome)

presidenza(presidente) --> cittadino(nome)

Quest'ultima traduzione è da preferire se il numero di istanze della relazione presidenza è piccolo rispetto al numero di istanze delle entità che vi partecipano.
Specializzazione
Vi sono diverse traduzioni possibili in questo caso, ognuna con pregi e difetti. Consideriamo il seguente esempio:
plot/spec1.png
Una traduzione che va bene qualsiasi sia il tipo della specializzazione è la seguente:

persona(codice, nome, cognome)

studente(codice, matricola)

lavoratore(codice, professione)

studente(codice) --> persona(codice)

lavoratore(codice) --> persona(codice)

Viene creata una tabella per ogni entità coinvolta nella specializzazione. Le tabelle delle sotto-entità ereditano dall'entità genitore la chiave, che diventa la loro chiave e anche chiave esterna riferita all'entità genitore. Il vincolo di chiave esterna realizza il vincolo di sotto-insieme tra istanze delle entità. Uno studente lavoratore è contenuto in entrambe le tabelle studente e lavoratore. Si noti che le tabelle delle sotto-entità non contengono gli altri attributi di persona (nome e cognome), e neppure le eventuali relazioni a cui persona partecipa. Infatti tali attributi e relazioni sono raggiungibili mediante la chiave esterna delle sotto-entità.

Rendiamo la specializzazione totale aggiungendo una sotto-entità disoccupato:
plot/spec2.png
Una traduzione alternativa che va bene quando la specializzazione è totale è la seguente:

studente(codice, nome, cognome, matricola)

disoccupato(codice, nome, cognome, anzianità)

lavoratore(codice, nome, cognome, professione)

L'entità genitore non viene tradotta ma tutti i suoi attributi vengono ereditati dalle tabelle delle entità figlie. Il vantaggio di questa traduzione è che, eliminando l'entità genitore, si riduce il numero di collegamenti tra tabelle necessari per il recupero dell'informazione. Inoltre, non impone vincoli di chiave esterna. Lo svantaggio è che istanze che appartengono a più sotto-entità vengono duplicate in più tabelle. Inoltre, eventuali relazioni a cui partecipa l'entità genitore devono essere duplicate in ogni entità figlia. Si noti che se la specializzazione fosse stata parziale, la traduzione di sopra è scorretta in quanto fa perdere le istanze dell'entità genitore non incluse in qualche sotto-entità.

Un'altra traduzione dell'ultimo schema proposto che rimane valida in tutti i casi è la seguente:

persona(codice, nome, cognome, tipo, matricola, anzianità, professione)

Abbiamo inglobato le entità figlie nell'entità genitore. Inoltre è stato aggiunto un nuovo attributo (tipo), che discrimina la sotto-entità a cui l'istanza appartiene. Ad esempio, per una istanza di studente, l'attributo tipo identifica la sotto-entità studente, l'attributo matricola contiene la matricola dello studente, e gli attributi anzianità e professione sono nulli.

Il vantaggio di questa traduzione è quello di usare una unica tabella. Questo riduce le operazioni di collegamento tra tabelle nel recupero dell'informazione. Inoltre, non impone vincoli di chiave esterna. Infine, rispetto alla soluzione precedente, possiamo accedere ad una unica tabella qualora conosciamo il codice di una persona ma non il suo tipo. Lo svantaggio è che ci potrebbero essere molti valori nulli in corrispondenza degli attributi specifici delle sotto-entità oppure quando la specializzazione è parziale. Si noti che anche eventuali relazioni associate alle entità figlie devono essere portate verso l'entità genitore, modificando la cardinalità minima di partecipazione dell'entità genitore a 0. Ad esempio, se uno studente partecipa alla relazione iscritto ad un unico corso di laurea con vincolo (1,1), una persona, che non è necessariamente uno studente, dovrà partecipare alla stessa relazione con vincolo (0,1). Questo cambiamento può introdurre ulteriori valori nulli.

Qualora la specializzazione sia sovrapposta, occorre scegliere con attenzione il dominio dell'attributo discriminante da aggiungere (qualora non esista). Una possibile soluzione è quella di usare come valore una sequenza di n bit, dove n è il numero di entità figlie. L'i-esimo bit identifica la partecipazione dell'istanza alla i-esima sotto-entità. Un'altra possibilità è quella di usare n campi distinti di tipo Booleano.

Specializzazioni multiple si traducono come le normali specializzazioni, facendo attenzione ad ereditare solo una volta attributi comuni. Ad esempio, lo schema:
plot/spec3.png
si traduce come segue:

persona(codice, nome, cognome)

studente(codice, matricola)

lavoratore(codice, professione)

studenteLavoratore(codice, rivalutazione)

studente(codice) --> persona(codice)

lavoratore(codice) --> persona(codice)

studenteLavoratore(codice) --> studente(codice)

studenteLavoratore(codice) --> lavoratore(codice)

Si noti che studenteLavoratore eredita l'attributo codice una sola volta ma esistono due vincoli di chiave esterna riferiti a studente e lavoratore. In tal modo affermiamo che un'istanza di studenteLavoratore appartiene a studente e anche a lavoratore.

Un caso particolare si ha quando l'ereditarietà multipla proviene da entità con chiavi diverse, come nel seguente caso:
plot/spec4.png
Una traduzione possibile è la seguente:

studente(matricola)

lavoratore(pIVA, professione)

studenteLavoratore(matricola, pIVA, rivalutazione)

studenteLavoratore(matricola) --> studente(matricola)

studenteLavoratore(pIVA) --> lavoratore(pIVA)

Si noti che la chiave di studenteLavoratore può essere scelta tra la chiave di studente e quella di lavoratore.

Nel caso di traduzione di un reticolo di specializzazioni, le varie traduzioni proposte possono essere combinate.
Avanti Indietro Indice
Basi di dati - Massimo Franceschet