Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
Guida al Visual Basic .NET - Introduzione ai database relazionali

Guida al Visual Basic .NET

Capitolo 71° - Introduzione ai database relazionali

<< Precedente Prossimo >>

Il modello relazionale non è stato il primo in assoluto ad essere usato per la gestione dei database, ma è stato introdotto più tardi, negli anni '70, grazie alle idee di E. F. Codd. Ad oggi, è il modello più diffuso e utilizzato per la sua semplicità.
Tale modello si basa su un unico concetto, la relazione, una tabella costituita da righe (o record o tuple) e colonne (o attributi). Per definire una relazione, basta specificarne il nome e gli attributi. Ad esempio:
Person (FirstName, LastName, BirthDay)
indica una relazione di nome Person, che presenta tre colonne, denominate rispettivamente FirstName, LastName e BirthDay. Una volta data la definizione, però, è necessario anche fornire dei dati che ne rispettino le regole: dobbiamo aggiungere delle righe a questa tabella per rappresentare i dati che ci interessano, ad esempio:

Relazione Person
FirstName LastName BirthDay
Mario Rossi 1/1/1965
Luigi Bianchi 13/7/1971
...

L'insieme di tutte le righe della relazione si dice estensione della relazione, mentre ogni singola tupla viene anche chiamata istanza di relazione. Facendo un parallelismo con la programmazione ad oggetti, quindi, avremo queste "somiglianze" (che si riveleranno di vitale importanza nella tipizzazione forte, come vedremo in seguito):
DatabaseProgrammazione ad oggetti
Relazione->   Classe
Tupla    ->   Oggetto
Estensione della relazione ->   Lista di oggetti
Attributo->   Propriet? dell'oggetto
Istanza di relazione ->   Istanza di classe (= Oggetto)
Avendo ora chiarito questi parallelismi, vi sarà più facile entrare nella mentalità del modello relazionale, dato che, se siete arrivati fino a qui, si assume che sappiate già benissimo tutti gli aspetti e i concetti della programmazione ad oggetti.
Uno sguardo attento, tuttavia, farà notare che, tra i caratteri fondamentali che si possono rintracciare in questi parallelismi, manca il concetto di "tipo" di un attributo. Infatti, per come abbiamo prima definito la relazione, sarebbe del tutto lecito immettere un numero intero nel campo FirstName o una stringa in BirthDay. Per fortuna, il modello prevede anche che ogni colonna possegga un dominio, ossia uno specifico range di valori che essa può assumere: ciò che noi abbiamo sempre chiamato tipo. Il tipo di un attributo può essere scelto tra una gamma molto limitata: interi, valori a virgola mobile, stringhe (a lunghezza limitata e non), date, caratteri, boolean e dati binari (array di bytes). In sostanza, questi sono i tipi primitivi o atomici di ogni linguaggio e proprio per questo motivo, si dice che il dominio di un attributo può essere solo di tipo atomico, ossia non è possibile costruire tipi di dato complessi come le strutture o le classi. Questa peculiarità sembrerebbe molto limitativa, ma in realtà non è così, poiché possiamo instaurare dei collegamenti (o vincoli) tra una relazione e l'altra, grazie all'uso di elementi detti chiavi.
La chiave più importante è la chiave primaria (primary key), che serve ad identificare univocamente una tupla all'interno della relazione. Facendo un paragone con la programmazione, se una tupla è assimilabile ad un oggetto ed esistono due tuple con attributi identici, esse non rappresentano comunque la stessa entità, proprio come due oggetti con proprietà uguali non sono lo stesso oggetto. E se per gli oggetti esiste un codice "segreto" per distinguerli (guid), a cui solo il programma ha accesso, così esiste un particolare valore che serve per indicare senza ombra di dubbio se due record sono differenti: questo valore è la chiave primaria. Essa è solitamente un numero intero positivo ed è anche la prima colonna definita dalla relazione. Modificando la definizione di Person data precedente, ed introducendo anche il dominio degli attributi, si otterrebbe:
'Questa sintassi è del tutto inventata!
'Serve solo per esemplificare i concetti:
Person (ID As Integer, FirstName As String, LastName As String, BirthDay As Date)
Relazione Person
ID FirstName LastName BirthDay
1 Mario Rossi 1/1/1965
2 Luigi Bianchi 13/7/1971
...

Per distinguere le singole righe esiste, poi, un'altra tipologia di chiave, detta chiave candidata, costituita dal più piccolo insieme di attributi per cui non esistono due tuple in cui quegli attributi hanno lo stesso valore. In generale, tutte le chiavi primarie sono chiavi canditate, a causa della stessa definizione data poco fa; mentre esistono chiavi candidate che non sono chiavi primarie. Ad esempio, in questo caso, l'insieme degli attributi FirstName, LastName e BirthDay costituisce una chiave candidata, poichè è praticamente impossibile trovare due persone con lo stesso nome nate nello stesso giorno alla stessa ora (almeno, è impossibile nella nostra relazione formata da due elementi XD e questo ci basta): quindi, questi tre attributi soddisfano le condizioni della definizione e identificano univocamente un record. In genere, si sceglie una fra tutte le chiavi candidate possibili che viene assunta come chiave primaria: a rigor di logica, essa dovrà essere la più semplice di tutte. In questo caso, il singolo numero ID è molto più maneggevole che non l'insieme di due stringhe e una data.
Ora, ammettiamo di avere una relazione così definita:
Program (ProgramID As Integer, Path As String, Description As String)
che indica un qualsiasi programma installato su un computer; e quest'altra relazione:
User (UserID As Integer, Name As String, MainFolder As String)
che indica un qualsiasi utente di quel computer. Ammettiamo anche che la macchina sulla quale sono installati i programmi presenti nell'estensione della relazione sia condivisa da più utenti: vogliamo stabilire, tramite relazioni, quale utente possa accedere a quale programma. In questa circostanza, abbiamo diverse soluzioni possibili, ma una sola è la migliore:
  • Abbiamo detto che la relazione Program ha una chiave primaria, e la relazione User pure. Dato che si tratta di due tabelle diverse, potrebbe venire in mente di stabilire questa policy di accesso: un utente può accedere a un programma solo se la sua chiave primaria (UserID) coincide con la chiave primaria del programma (ProgramID). In questo caso, tuttavia, le circostanze sono molto restrittive, in quanto un utente può usare uno e un solo programma (e viceversa). La relazione (in senso letterale, ossia il collegamento) tra le due tabelle si dice uno a uno.
  • Aggiungiamo alla relazione Program un altro attributo UserID, che dovrebbe indicarci l'utente che può usare un dato programma. Tuttavia, come abbiamo visto prima, i valori delle colonne devono essere atomici e perciò non possiamo inserire in quella singola casella tutta un'altra riga (anche perchè non sapremmo che tipo specificare come dominio). Qui ci viene in aiuto la chiave primaria: sappiamo che nella relazione User, ogni tupla è univocamente identificata da una e una sola chiave primaria chiamata UserID, quindi indicando una chiave, indichiamo anche la riga ad essa associata. Per cui, possiamo ben creare un nuovo attributo di tipo intero (in quanto la chiave è un numero intero in questo caso), nel quale specifichiamo l'UserID dell'utente che può usare il nostro programma. Ad esempio:
    Program (ProgramID As Integer, Path As String, Description As String, UserID As String)
    Relazione Program
    ProgramID Path Description UserID
    1 C:WINDOWS otepad.exe Editor di testo 2
    2 C:ProgrammiFireFoxfirefox.exe FireFox web browser 1
    3 C:ProgrammiWorld of WarcraftWoW.exe World of Warcraft 2
    ...

    Relazione User
    UserID Name MainFolder
    1 Mario Rossi C:UsersMRossi
    2 Luigi Bianchi C:UsersGigi
    ...

    Come evidenziano i colori, il programma 1 (notepad) e il programma 3 (World of Warcraft) possono essere usati dall'utente 2 (Luigi Bianchi), mentre il programma 2 (Ffirefox) può essere usato dall'utente 1 (Mario Rossi). Da un programma possiamo risalire all'utente associato, controllarne l'identità e quindi consentirne o proibirne l'uso. Questa soluzione, tuttavia, permette l'accesso a un dato programma da parte di un solo utente, anche se tale utente può usare più programmi.
    La relazione che collega User a Program è detta uno a molti (un utente può usare più programmi). Se la guardiamo al contrario, ossia da Program a User, è detta molti a uno (più programmi possono essere usati da un solo utente). Entrambre le prospettive sono le due facce della stessa relazione uno a molti, la più utilizzata.
  • Dato che il precedente tentativo non ha funzionato, proviamo quindi a introdurre una nuova tabella:
    UsersPrograms (UserID As Integer, ProgramID As Integer)
    In questa tabella imponiamo che non esista alcuna chiave primaria. Infatti lo scopo di questa relazione è un altro: ad un certo programma associa un utente, ma questo lo si può fare più volte. Ad esempio:

    Relazione Program
    ProgramID Path Description
    1 C:WINDOWS otepad.exe Editor di testo
    2 C:ProgrammiFireFoxfirefox.exe FireFox web browser
    3 C:ProgrammiWorld of WarcraftWoW.exe World of Warcraft
    ...

    Relazione User
    UserID Name MainFolder
    1 Mario Rossi C:UsersMRossi
    1 Luigi Bianchi C:UsersGigi
    ...

    Relazione UsersPrograms
    UserID ProgramID
    1 1
    1 2
    2 2
    2 3
    ...

    Nell'ultima relazione troviamo un 1 (due volte) associamo prima ad un 1 e poi ad un 2: significa che lo stesso utente 1 (Mario Rossi) può accedere sia al programma 1 (notepad) sia al programma 2 (firefox). Allo stesso modo, l'utente 2 può accedere sia al programma 2 (firefox) sia al programma 3 (World of Warcraft). Con l'aggiunta di un'altra tabella siamo riusciti a legare più utenti a più programmi. Relazioni tra tabelle di questo tipo si dicono molti a molti.
In ognuno di questi esempi, l'intero con cui ci si riferisce ad un'altra tupla viene detto chiave esterna.

<< Precedente Prossimo >>
A proposito dell'autore

C#, TypeScript, java, php, EcmaScript (JavaScript), Spring, Hibernate, React, SASS/LESS, jade, python, scikit, node.js, redux, postgres, keras, kubernetes, docker, hexo, etc...