La strutturazione dei database: Il modello relazionale (3/3)

Nei due precedenti articoli di questa serie (la chiave primaria e la normalizzazione dei database) abbiamo gettato le basi per organizzare delle strutture di database conformi ai principi dell’efficienza, della mantenibilità e al riparo dal fenomeno dell’inconsistenza.
Ora vedremo nella pratica la progettazione di un database. Nella fattispecie si tratterà di un database per un’applicazione che permette di proporre degli eventi ai quali altri utenti possono iscriversi. Ovviamente vedremo solo la parte che riguarda lo sviluppo della struttura del database.

Breve accenno al modello entità-relazioni

Prima di iniziare proviamo a definire il nostro database tramite il modello entità-relazione. Lo farò in modo molto semplificato.

ENTITA’:
Nella progettazione di database, si definiscono entità i gruppi di informazioni omogenee. Nel nostro caso avremo l’entità utenti e l’entità eventi.
Ogni entità avrà degli attributi ovvero quelle informazioni che hanno un legame logico tra di loro. Ad esempio l’entità utenti avrà come attributi il nome utente, l’email, la password, eccetera.

RELAZIONI:
Ogni volta che vogliamo definire un dato che fa riferimento a due o più entità lo faremo attraverso delle relazioni. Ad esempio:
Chi (entità utenti) ha promosso questo evento (entità eventi)?
Questa relazione è definita come relazione uno a molti. Infatti ogni evento è promosso da un solo utente che però può promuovere più eventi.
Oppure:
Quali utenti (entità utenti) sono iscritti a quali eventi (entità eventi)?
In questo caso la relazione sarà definita molti a molti, perchè diversi utenti possono iscriversi a diversi eventi. Come vedremo, per descrivere questa relazione, creeremo un’apposita tabella.

La tabella utenti

Iniziamo con il descrivere quella che potrebbe essere la tabella utenti

La tabella è semplice; contiene la chiave primaria, l’username, la password, l’email ed infine il numero di eventi promossi dall’utente.
I lettori più attenti a questo punto potrebbero muovere la prima obiezione: l’email è un dato univoco, non possono esserci due utenti con lo stesso email (inoltre, al momento della registrazione, non permetteremo ad un utente di registrarsi con un email già presente nel database). Di conseguenza il campo email potrebbe essere la chiave primaria di questa tabella, e potremmo rimuovere la colonna id_utente.
La risposta a questa obiezione non è netta. In generale sì, il campo email potrebbe essere una chiave candidata ma…
Nello specifico di un’applicazione web è comunque preferibile avere a che fare con un dato numerico o comunque semplice. Pensate ad esempio che la chiave primaria è spesso fatta passare attraverso alla querystring dell’url. Passare un numero è certamente meglio di passare un indirizzo di posta elettronica. Dunque manteniamo la colonna id_utente.
Un’anomalia comunque in questa tabella c’é. La colonna che rappresenta il numero di eventi promossi da ciascun utente (num). E’ un dato che sarà possibile ricavare; quindi è inutile memorizzarlo.
La colonna num andrà quindi eliminata.

La tabella eventi

Vediamo ora come potrebbe essere rappresentata la tabella eventi. dovremo prevedere una chiave primaria, in seguito inseriremo il titolo dell’evento, la sua descrizione, la data, chi lo ha promosso e chi intende parteciparvi.

Bene. Questa tabella contiene almeno due anomalie. Innanzitutto è un’errore inserire l’username nel campo promotore.
Cosa succederebbe se l’utente decidesse di cambiare il suo username? Ad esempio se Maurizio modificasse il proprio username in mau?
Nella lista degli utenti figurerebbe come mau, mentre negli eventi risulterebe ancora Maurizio.
Se ci mettiamo dal punto di vista del sistema, i dati non sono coerenti. Come è possibile che Maurizio, che non é un utente, abbia promosso degli eventi?
Questo è un esempio semplicissimo di inconsistenza. I dati nelle diverse tabelle del database non sono coerenti e quindi non affidabili.

La soluzione a questo incoveniente sta nel corretto uso della relazionalità. Al posto dell’username (che non è una dato necessariamente stabile), utilizzeremo la chiave primaria che fa capo all’username, applicando così quella che viene detta una relazione uno a molti.

Quando andremo ad estrarre i dati dei vari eventi, per risalire al nome del promotore, dovremo fare quella che si chiama una JOIN tra la tabella eventi e la tabella utenti.
In pratica dovremo dire: il titolo è ciò che è contenuto nel campo titolo, la descrizione ciò che è contenuto nel campo descrizione, il promotore invece è il campo username della tabella utenti che ha come chiave primaria il dato inserito nella colonna promotore della tabella eventi. Wow. Questo tradotto in una query (anche se non è l’obiettivo dell’articolo entrare in materia di query) potrebbe essere espresso così:

 SELECT * FROM eventi,utenti WHERE utenti.id_utente=eventi.promotore
 

Questa query in pratica collega la tabella eventi e la tabella utenti utilizzando come riferimento il contenuto del campo promotore della tabella eventi che dovrà essere uguale al contenuto del campo id_utente della tabella utenti dando luogo ad una nuova tabella (anche se “virtuale”) che avrà questo aspetto (ho tralasciato alcuni campi per praticità).

La seconda anomalia è evidente. Il dato iscritti non è un valore atomico (dunque la tabella non è nemmeno in prima forma normale). E’ un modo scomodo e sbagliato di memorizzare i dati.
Per risolvere questa anomalia dovremo spostare questo dato su di un’altra tabella, chiamiamola tabella iscritti, tramite quella che viene definita una relazione molti a molti, in questo modo

Come vedi, l’evento con chiave 1 è associato agli utenti con chiave 1, 2 e 3. Questo significa che all’evento “Compleanno di Maurizio” (Id_evento = 1) parteciperanno Maurizio (Id_utente = 1), Luigi (Id_utente = 2) e Gianni (Id_utente = 3) .
Bene, il nostro database è ora normalizzato e relazionato correttamente e si presenta in questo modo

Proteggiamo le relazioni

Senza andare a scomodare il complesso discorso sui vincoli di integrità, dobbiamo sempre domandarci come le relazioni che abbiamo stabilito ed in generale i dati nel nostro database possano essere messi in pericolo da operazioni di inserimento, modifica o cancellazione.
Abbiamo visto in precedenza come la modifica dell’username, senza i dovuti accorgimenti, avrebbe potuto dare luogo a delle incoerenze nei dati.
Ora ci troviamo di fronte ad un tipico problema che si verifica ogni volta che abbiamo un’applicazione con degli utenti. Cosa succede se elimino un utente?
Eliminiamo ad esempio l’utente Maurizio. Nella tabella eventi ci saranno due righe che fanno capo alla chiave primaria 1 (che era la chiave di Maurizio), e nella tabella iscritti avremo due righe alle quali è associata sempre questa chiave primaria. Ma questa chiave ora non esiste più. Questo è un problema serio.

SOLUZIONI:
In questo caso, le soluzioni le possiamo trovare a livello di applicazione. La soluzione più radicale potrebbe essere: “non è possibile eliminare un utente”.
Esistono altre soluzioni, WordPress ad esempio (che ovviamente ha lo stesso problema quando vogliamo eliminare un utente) ne propone due:

Come vedi le soluzioni proposte da WordPress sono:

  • Eliminare l’utente e tutti i suoi articoli (nel nostro caso sarebbe tutti gli eventi che ha promosso e tutte le iscrizioni che ha fatto), anche questa è una soluzione radicale.
  • Attribuire gli articoli ad un altro autore

Io ne aggiungerei una più accettabile. Disattivare l’utente mantenendone comunque i dati in memoria.

Presta sempre molta attenzione a questi aspetti nella progettazione di un’applicazione.

Conclusione

Siamo giunti alla fine di questa serie di articoli che volevano dare la basi per una corretta progettazione di database. Il resto come sempre lo fa l’esperienza. Il fatto di trovarsi in un mare di guai per aver mal strutturato una database ci darà la certezza di farne uno migliore la prossima volta. E’ comunque un fatto che la struttura di un database vada progettata in modo molto accurato, non sappiamo quanto potrà crescere nel tempo.
Ricordo uno studente di Harvard che ha creato una stupida applicazione, una specie di annuario computerizzato. Ebbene, sei anni dopo si è ritrovato con 500 milioni di iscritti…

Tag:

L'autore

Maurizio è sposato con la triade PHP - MySql - Apache e, non pago, ha un'amante chiamata jQuery. Ha un blog dove cerca di descrivere nei minimi particolari sia la moglie che l'amante. La sua vera specialità è la realizzazione di gestionali complessi anche se non rifiuta mai un sito web. +

Sito web dell'autore | Altri articoli scritti da

Articoli correlati

Potresti essere interessato anche ai seguenti articoli:

7 commenti

Trackback e pingback

  1. Tweets that mention La strutturazione dei database: Il modello relazionale (3/3) | Your Inspiration Web -- Topsy.com
    [...] This post was mentioned on Twitter by Your Inspiration Web, mtx_maurizio. mtx_maurizio said: RT @YIW La strutturazione dei database:…