LE BASI DI DATI: GENERALITÀ In ogni modello di organizzazione di vita, abbiamo bisogno di trattare informazioni che vanno raccolte, dopo averle individuate, per poi: 1) 2) 3) 4) Recuperarle in base a criteri di ricerca Aggiungerne di nuove Modificarle apportando variazioni Cancellarle se non più necessarie In Informatica, la teoria delle basi di dati studia proprio l’organizzazione delle informazioni, per poterle gestire in modo semplice ed efficiente in termini di memoria o spazio e di tempo, efficace e sicuro. Una base di dati o Database è una raccolta di dati logicamente correlati e progettati per essere usati in maniera ottimizzata da differenti utenti ed applicazioni. Una base di dati può avere diverse dimensioni e deve essere: 1) Sicura, in modo da non essere danneggiata in maniera accidentale e non. 2) Integra, in modo da non perdere i dati. 3) Consistente, contenente cioè dati significativi. 4) Persistente, con un tempo di vita non limitato alle singole esecuzioni di programmi che lo utilizzano. Le informazioni necessarie sono gestite dal SISTEMA INFORMATIVO, che è: Un insieme organizzato di strumenti automatici, procedure manuali, norme, risorse umane e materiali, orientato alla gestione delle informazioni rilevanti per un’organizzazione intesa come raccolta, archiviazione, elaborazione e scambio di informazioni. La parte del sistema informativo che può essere automatizzata è detta SISTEMA INFORMATICO ed è: L’insieme degli strumenti informatici usati per il trattamento automatico delle informazioni. DATI E INFORMAZIONI Il termine DATO significa “fatto”. Lo scopo dei dati è quello di codificare i fatti ritenuti importanti. L’INFORMAZIONE è la conoscenza acquisita dei dati. I dati sono utilizzabili solo se possono essere interpretati, cioè se si comprende il loro significato. Definiamo SCHEMA, la chiave di interpretazione dei dati, mentre chiamiamo ISTANZA di uno schema, l’insieme dei valori assunti da esso in un certo intervallo di tempo. Esempio: Art 01 12 Art02 Schema che non dà informazioni utili, a differenza dello schema sottostante 45 CODICE ARTICOLO QUANTITÀ Art01 Art02 12 45 Definiamo CATEGORIA un gruppo di dati aventi lo stesso schema. Definiamo OCCORRENZA di un database l’insieme delle istanze delle categorie in un dato istante di tempo. IL MODELLO DEI DATI Un modello di dati è un insieme di concetti e costrutti usati per organizzare i dati descrivendone struttura, associazioni e vincoli. Esistono vari modelli: 1) Modelli concettuali: cercano di descrivere i concetti del mondo reale. Essi sono usati nella fase preliminare di progettazione e il più noto è il modello E/R. 2) Modelli logici: consentono una specifica rappresentazione dei dati attraverso tabelle, grafi, alberi, oggetti, e descrivono ciò che l’utente finale può vedere. Tra questi modelli abbiamo: a) Modello gerarchico: piuttosto obsoleto, in cui i dati sono connessi secondo una struttura ad albero, con una forte dipendenza dei programmi alle strutture, causa di ridondanze ed inconsistenze. b) Modello reticolare: la struttura è ad anello con accesso ai dati più semplice, anche se tale struttura è abbastanza complessa e la sua modifica comporta la cancellazione dell’intero database. c) Modello ad oggetti: molto meno moderno, è un’evoluzione del modello relazionale e viene usato per applicazioni multimediali. PROGETTAZIONE DI UN DATABASE E SUE FASI Le fasi di progettazione di un database sono tre: 1) PROGETTAZIONE CONCETTUALE: ha lo scopo di trasformare la rappresentazione astratta in uno schema logico (tabelle). 2) PROGETTAZIONE FISICA: ha lo scopo di implementare lo schema logico definendone gli aspetti fisici di memorizzazione in memoria di massa. IL DBMS Il DBMS è un insieme di strumenti software che, sulla base delle specifiche dell’utente, genera lo schema per aggiornare i dati. Le funzioni che un DBMS deve assolvere sono: 1) Gestione del database, con inserimento, cancellazione, aggiornamento e interrogazione dello stesso. 2) Persistenza e consistenza, cioè la conservazione del contenuto del database in caso di guasti o malfunzionamenti. 3) Privatezza e sicurezza dei dati attraverso meccanismi di autorizzazione. 4) Integrità dei dati mediante il controllo sui vincoli imposti per un dato database. Un DBMS deve inoltre essere efficiente ed efficace. LA PROGETTAZIONE CONCETTUALE: IL MODELLO E/R La progettazione concettuale consiste nel riorganizzare tutti gli elementi a disposizione per rappresentare la realtà di interesse. Il documento ufficiale è lo SCHEMA CONCETTUALE, che serve poi per la successiva fase logica. Il più diffuso modello concettuale è quello E/R o Entità/Associazioni, ed è un modello grafico per la descrizione dei dati e delle loro relazioni. Per la costruzione di uno schema E/R, si parte dal concetto che la realtà da rappresentare sia composta da ENTITÀ, ognuna delle quali è caratterizzata da proprietà dette ATTRIBUTI. Le varie entità sono connesse tra loro attraverso ASSOCIAZIONI. LE ENTITÀ Le entità sono ciò che esiste nella realtà che si vuole modellare come ad esempio il libro “I Promessi Sposi” dalla biblioteca che si sta esaminando. Gli attributi sono i fatti che si intende rappresentare e descrivono le entità, come ad esempio il numero di pagine di un libro. Ogni singolo esemplare appartenente ad una certa entità si dice ISTANZA. Ad esempio “I Promessi Sposi” è un’istanza dell’entità Libri. GLI ATTRIBUTI Possiamo dire che gli attributi semplici per l’entità Persona, sono ad esempio: Nome, Cognome, Età, Sesso. In sostanza ogni attributo è specificato da: 1) 2) 3) 4) Nome Formato, cioè il tipo di valori che assume Dimensione, cioè la quantità massima di caratteri o cifre Valore, il cui insieme determina il DOMINIO dell’attributo Nel caso dell’entità Persona, abbiamo che il dominio dell’attributo Età va da 1 fino a 100, mentre il dominio del Sesso è {uomo, donna}. Un attributo è OBBLIGATORIO se il suo valore è non nullo (Nome, Cognome), mentre è FACOLTATIVO se può essere vuoto (Titolo di studio) e coincide con il valore NULL. Inoltre abbiamo gli attributi COMPOSTI che risultano dall’aggregazione di più attributi semplici, come ad esempio l’attributo DataDiNascita, composto da giorno, mese ed anno. Esistono anche gli attributi MULTIPLI, come ad esempio Hobby. L’esigenza di creare un oggetto come entità piuttosto che come attributo o viceversa, dipende dal contesto e dall’uso che ne vogliamo fare. Se di un certo concetto vogliamo descrivere un insieme di proprietà, si crea un’entità. ATTRIBUTI CHIAVE Si definisce CHIAVE CANDIDATA o SUPERCHIAVE una chiave che consente di distinguere un’istanza di entità dall’altra in modo univoco. Ad esempio per l’entità Persona, possiamo dire che l’attributo CodiceFiscale, diverso per ogni individuo, è una CHIAVE PRIMARIA, con minor numero di attributi. RAPPRESENTAZIONE ATTRIBUTI GRAFICA DI ENTITÀ ED <Chiave Primaria> <Nome Attributo1> <Nome_Entità> <Nome Attributo2> LE ASSOCIAZIONI L’associazione è un legame logico tra due o più entità rilevanti nella realtà considerata. L’ISTANZA di un’associazione è una combinazione di istanze delle entità che prendono parte all’associazione. <associa zione> <Nome_Entità1> <Attributo1 > <Nome_Entità2> <Attributo1 > Ogni associazione tra due entità ha due versi. Così, ad esempio, tra l’entità Persona e l’entità Automobile esiste l’associazione “Possiede”, mentre nel verso contrario l’associazione è “è posseduta”. Di solito si hanno associazioni binarie, come quella vista poco fa, ma esistono anche associazioni multiple, che collegano più di due entità e che spesso possono essere scomposte in binarie. Possono anche esistere attributi cha da un’associazione passano ad un’entità, e questo avviene di solito se un attributo ha un valore fisso e può essere identificato anche nell’entità. Un attributo può diventare un’entità quando ad esso possono attribuirsi vari attributi, evitando la duplicazione. CodFiscale Nome Cognome RagioneSocialeDitta Persona Dipende Persona CodFiscale Nome Cognome Ditta RagioneSocialeDitta indirizz o Verifica Studente Mese Ditta Anno Voto Giorno Telefono Anno TIPI DI ASSOCIAZIONI Un’associazione diretta tra due entità X e Y si dice TOTALE quando il legame tra entità deve essere sempre presente e ad ogni elemento di X deve corrispondere almeno un elemento di Y, e la sua rappresentazione grafica è una linea tratteggiata. possiede Persona ContoCorrente Una persona può possedere un conto corrente (parzialità) e un conto corrente deve essere intestato ad almeno una persona (totalità). Chiamiamo CARDINALITÀ di un’associazione tra X e Y la descrizione della molteplicità diretta dell’associazione e di quella inversa, dove per molteplicità intendiamo quante istanze di Y possono trovarsi in relazione con un’istanza di X e viceversa. Le associazioni si classificano in: 1) UNO AD UNO (1:1): si verifica quando ad un’istanza di corrisponde una ed una sola istanza di Y e viceversa. Dirigente scolastico Dirige 1 1 Scuola Associazione diretta: un dirigente scolastico dirige una scuola. Associazione inversa: una scuola è diretta da un solo dirigente scolastico. L’associazione diretta potrebbe essere anche parziale, se si considerano ad esempio i presidi in pensione. 2) UNO A MOLTI (1:N): si verifica quando ad un’istanza di X possono corrispondere una o più istanze di Y, e ad ogni istanza di Y deve corrispondere una sola istanza di X. Scuola 1 HaInOrga nico NPersonaleSegreteria Associazione diretta: una scuola ha in organico più personale docente. Associazione inversa: una persona di segreteria lavora in una sola scuola. 3) MOLTI A MOLTI (N:N): si verifica quando ad ogni istanza di X possono corrispondere una o più istanza di Y e viceversa. Professore Classe Insegna N N Associazione diretta: un professore insegna in più classi. Associazione inversa: in una classe insegnano più professori. VINCOLI DI INTEGRITÀ I vincoli di integrità sono restrizioni sui possibili valori relativi ai fatti che si vogliono rappresentare e sui modi in cui possono evolvere nel tempo. Esistono vincoli impliciti, che possono essere: 1) Di chiave primaria: le istanze di una categoria devono essere tutte diverse tra loro 2) Referenziali: date due entità A e B e un’associazione, non esiste un elemento di A che non sia associato ad un elemento di B. Abbiamo poi i vincoli espliciti che impongono delle restrizioni sul modo in cui i dati possono cambiare. Ad esempio “il valore dell’attributo età non può essere negativo né maggiore di 120”, è un vincolo esplicito, cioè tradotto in simboli abbiamo: V1: (0< età <120). V1(PERSONA): (0< età <120) V2(DIPENDENTE) : DataAssunzione > DataNascita V3(DIPENDENTE): Trattenute >0 LA PROGETTAZIONE LOGICA: IL MODELLO RELAZIONALE Il passo successivo nella progettazione concettuale di una base di dati è la progettazione logica, che consiste nel trasformare la rappresentazione ancora astratta in una più efficiente, detta SCHEMA LOGICO RELAZIONALE. In sostanza si tratta di convertire il diagramma E/R in un insieme di tabelle e nella definizione delle operazioni da compiere sullo schema. Definiamo schema di una relazione il nome della stessa e la lista dei suoi attributi, in questo modo: Persona(Cognome:Stringa(30),Nome:Stringa(20),Età: Intero, Sesso:Booleano) o anche: Persona ( Cognome, Nome, Età, Sesso) Esempi: 1) Rappresentazione per elencazione: PERSONA( Cognome, Nome, Età, Sesso) = { (Rossi, Paolo, 30; Maschio) (Bianchi, Antonio, 23, Maschio) (Neri, Ada, 35, Femmina) tupla tupla tupla 2) Rappresentazione mediante tabella: PERSONA COGNOME NOME Rossi Paolo Tuple (righe) Bianchi Antonio Neri Ada colonne (attributi) ETÀ 30 23 35 3) Rappresentazione insiemistica: (Rossi, Paolo,30, Maschio) (Bianchi, Antonio,23, Maschio) (Neri,Ada,35,Femmina) SESSO Maschio Maschio Femmina Per ogni relazione deve esistere una CHIAVE. In generale una relazione può ammettere diverse chiavi che si dicono CANDIDATE, ma tra queste ne viene scelta una, detta CHIAVE PRIMARIA, che viene sottolineata nello schema. I legami tra le relazioni si realizzano proprio usando tali chiavi. DAL DIAGRAMMA E/R ALLO SCHEMA RELAZIONALE Lo schema relazionale si ricava dal diagramma E/R applicando le regole di derivazione, per rappresentare: 1) Entità e attributi 2) Associazioni 1:1, 1:N, N:N 3) Gerarchie di classi In particolare possiamo affermare che: 1) Ogni entità diventa una relazione, cioè una tabella 2) Ogni attributo dell’entità lo diventa nella relazione ed è rappresentato mediante colonna 3) La chiave dell’entità diventa chiave nella relazione. RAPPRESENTAZIONE DELLE ASSOCIAZIONI In un’associazione di tipo 1:N tra due entità A e B, la chiave primaria di A diventa CHIAVE ESTERNA di B, cioè essa funge da puntatore logico alla tupla dell’altra relazione (A) alla quale è associata. Ricordiamo che non si può cancellare una tupla la cui chiave primaria compaia in almeno una tupla di altre relazioni come chiave esterna. Studente Matricola Cognome Nome CodScuola frequenta Scuola CodScuola NomeScuola Esterna indirizzo Il meccanismo delle chiavi esterne comporta di sicuro una duplicazione delle informazioni, per questo, spesso si preferisce usare una chiave detta ARTIFICIALE, costituita da un numero progressivo o contatore. Le associazioni di tipo 1:1 sono un caso particolare delle 1:N e seguono le loro stesse regole, anche se generalmente si preferisce in questi casi riunire i due tipi di entità in un’unica relazione contenente tutti gli attributi dell’una e dell’altra entità. Le associazioni di tipo N:N tra due entità A e B si crea mediante una nuova relazione avente almeno le chiavi primarie di A e di B, ed eventualmente anche attributi propri. Un caso particolare di associazioni 1:N o N:N è quello in cui l’entità di partenza è uguale a quella di arrivo. In questo caso si opera allo stesso modo delle associazioni con più entità e si parla di associazione RICORSIVA. AbitaCon CodFiscale Condomino Cognome Nome Condomino (CodFisc; Cognome, Nome) AbitaCon(CodFisc1, CodFisc2) Esistono anche associazioni non binarie, ma esse vengono in genere trattate come quelle binarie. Prodotto CodProd descrizione Data HaFatturato Condomino CodCli Cognome Nome Condomino CodCassa Posizione L’INTEGRITÀ REFERENZIALE I vincoli di integrità referenziale riguardano i valori assunti dalle chiavi esterne nelle relazioni. Infatti, poiché una chiave esterna è utilizzata per stabilire un legame tra relazioni, il suo valore deve essere tenuto in stretto controllo per operazioni di modifica, cancellazione ed inserimento. Infatti, per cancellare una tupla da una relazione, occorre verificare che non ci siano tuple in altre relazioni che facciano riferimento alla tupla da cancellare. L’integrità referenziale è assicurata direttamente dal DBMS attraverso regole di validazione attraverso appositi linguaggi dichiarativi. LE OPERAZIONI RELAZIONALI Vediamo le operazioni che consentono di interrogare una base di dati, cioè di ottenere le informazioni desiderate estraendo una sottotabella da una tabella. Le interrogazioni seguono le regole dell’ALGEBRA RELAZIONALE e generano una nuova relazione. L’insieme degli operatori utilizzati nelle interrogazioni sono: 1) UNIONE 2) DIFFERENZA – π σ 3) PROIEZIONE 4) SELEZIONE 5) PRODOTTO 6) INTERSEZIONE 7) CONGIUNZIONE X ∩ UNIONE E DIFFERENZA DI RELAZIONI Per effettuare l’unione tra due relazioni, esse devono essere compatibili, cioè devono avere lo stesso numero di attributi e gli stessi occupanti la stessa posizione nelle due relazioni, sono dello stesso tipo, come ad esempio le entità sottostanti: Persona (Nome : Stringa, Stipendio : Intero, DataN : Data) Dipendente (Nominativo : Stringa, Stip : Intero, DNascita : Data) R S = {t / tT or TS} Anche nella differenza, le due relazioni devono essere compatibili e si ha: R – S = {t / tT and TS} La differenza non è commutativa. Es: per quanto riguarda l’unione, se R rappresenta i clienti del primo semestre di un’attività di un’azienda ed S i clienti del secondo semestre, R S rappresenta i clienti dell’anno. Es: per quanto riguarda la differenza, se R rappresenta tutti i clienti di un’azienda ed S i clienti dell’anno 2005, R – S rappresenta tutti i clienti esclusi quelli del 2005. LA PROIEZIONE L’effetto di una proiezione su una relazione è quello di selezionare un certo numero di colonne dalla tabella della stessa relazione. Supponiamo di avere la relazione R: Clienti (CodCli, Nome, Agente, Indirizzo) e di voler estrarre solo il nome degli agenti e l’indirizzo. Avremo la seguente proiezione: S = π Agente, Indirizzo(R) LA SELEZIONE L’effetto di una selezione è quello di selezionare un certo numero righe dalla tabella della relazione. Supponiamo di avere la tabella R: Clienti (CodCli, Nome, Provincia, Indirizzo) E di voler selezionare le informazioni relative ai clienti solo della provincia di Milano. Avremo quindi: S = σ provincia = “MI”(R) IL PRODOTTO CARTESIANO In questo caso, date due relazioni R ed S, il prodotto si effettua concatenando ogni tupla di R con ogni tupla di S. R X S = {t / t = r con s,r R,s S} Ad evitare ogni ambiguità nei nomi degli attributi di R X S, occorre che i nomi degli attributi di R e di S siano diversi tra loro, altrimenti bisogna ridenominarli. Es: abbiamo una relazione R che rappresenta gli alunni di una classe terza, e una relazione S che rappresenta i testi adottati per quella stessa classe. Vogliamo costruire una tabella con l’elenco di tutti i testi per alunno. L’INTERSEZIONE Date due relazioni R ed S, la loro intersezione restituisce la relazione composta da tutte le tuple presenti sia in R sia in S. R ∩ S = {t / t R and t S} LA CONGIUNZIONE Lo scopo della congiunzione è quello di combinare due relazioni aventi uno o più attributi, generando una nuova relazione che contiene: 1) Le colonne della prima e della seconda tabella senza duplicazioni. 2) Le righe della prima concatenata a quelle della seconda, secondo i valori uguali dell’attributo comune. Si indica l’equazione di congiunzione con il simbolo : R S A=B 3) Eliminando l’attributo CodAgente, si ottiene la relazione finale di congiunzione: CODCLI NOMECLI INDIRIZZOCLI NOMEAGENTE TELAGENTE C006 C002 C005 Bianchi Neri Rossi A0052 A0016 A0052 Rinaldi Polis Rinaldi 322/7665541 346/5647523 322/7665541 LA NORMALIZZAZIONE DELLE TABELLE Se lo schema della base di dati non è costruito correttamente, può accadere che si abbiano delle anomalie nel database, come ad esempio la ripetizione dei dati. Vediamo in dettaglio le anomalie: 1) Anomalie in inserimento: se abbiamo due entità Cliente e Articolo legate tra loro, si ha che per inserire un nuovo cliente è necessario inserire anche un articolo ordinato. Allo stesso modo non è possibile inserire un nuovo articolo senza specificare un acquirente, e ciò perche la chiave primaria della relazione è CodCliente e CodArticolo e non può essere nulla. 2) Anomalie in cancellazione: se si cancella un record relativo ad un acquisto, si corre il rischio di cancellare anche i dati relativi al cliente. 3) Anomalie in aggiornamento: se occorre variare l’indirizzo di un cliente, occorrerà anche aggiornare ogni record in cui compare quel cliente. Queste anomalie sono conseguenza della ridondanza, cioè la presenza di dati ripetuti inutilmente. In questo contesto si colloca la teoria della NORMALIZZAZIONE che è un procedimento che consente di verificare se la definizione dello schema corrisponde ai canoni standard di correttezza del database, avvalendosi di un preciso insieme di regole che riportano le tabelle in FORME NORMALI. La teoria della normalizzazione si riassume nelle seguenti regole: 1) Ogni tabella deve avere una chiave primaria 2) Ogni campo deve contenere un solo valore 3) I campi di una tabella non devono dipendere da altri campi che non siano la chiave primaria. 4) Bisogna evitare le ripetizioni e la ridondanza. LA PRIMA FORMA NORMALE (1FN) La forma 1FN dice che ogni campo deve avere un solo valore, cioè deve essere un campo semplice (non composto né multiplo), e ci deve essere una chiave primaria. Ad esempio se in una tabella abbiamo il campo Indirizzo composto da NomeVia, Numero e Città, si scompone il campo in più campi semplici e con meno informazioni. Se ad esempio abbiamo un campo multiplo, con la presenza di più numeri di telefono, si scompone l’unica entità con due entità separate, di cui una contenente il campo con attributo multiplo e la chiave primaria della relazione. LA SECONDA FORMA NORMALE (2FN) Una relazione R è in 2FN innanzitutto se è in 1FN e ogni attributo non chiave dipende completamente dalla chiave primaria. Tutti i campi diversi dalla chiave primaria devono dipendere dall’intera chiave e non da una sua parte. Consideriamo la seguente relazione: Ordini(CodOrdine,CodCliente,CodProdotto,DataOrdine,Quantità,Prezzounit, Descrizione) Lo schema presenta delle anomalie che sono: 1) In inserimento, cioè non si può inserire un nuovo articolo in magazzino fino a quando non viene ordinato, e questo perché CodOrdine e CodProdotto non possono essere nulle. 2) In cancellazione, cioè se si cancellano delle righe si perdono informazioni sugli articoli. 3) In aggiornamento, cioè se varia il prezzo unitario di un articolo, bisogna aggiornare tutti i record in cui esso compare, con i relativi totali. Vediamo le dipendenze funzionali della chiave primaria CodOrdine e CodProdotto. Si ha: CodOrdine CodCliente CodOrdine, CodProdotto DataOrdine, Quantità CodProdotto PrezzoUnit, Descrizione Queste sono le dipendenze dei vari attributi dalle chiavi. Per risolvere i problemi derivanti dalle dipendenze, si deve scomporre la relazione di partenza in relazioni più semplici, ciascuna relativa ad una data categoria Ordini, prodotti e ProdottiOrdinati, tutte e tre collegate tramite chiavi primarie ProdottiOrdinati (CodOrdine, CodProdotto, Quantità) Prodotti ( CodProdotto, PrezzoUnit, Descrizione) Ordini ( CodOrdine, DataOrdine, CodCliente) In questo modo le anomalie non sono più presenti e attraverso le chiavi primarie è possibile recuperare tutte le informazioni. Riassumendo, per normalizzare: Nello schema originario rimane la chiave primaria e tutti gli attributi non chiave dipendenti completamente da essa. Si crea un nuovo schema di relazione per ogni parte di chiave primaria da cui dipendono completamente altri attributi non chiave In sostanza esiste sempre una scomposizione delle relazioni di partenza. LA TERZA FORMA NORMALE (3FN) Una relazione R è 3FN se innanzitutto è in 2FN e ogni attributo non chiave dipende direttamente dalla chiave, cioè attributi non chiave che dipendono da altri attributi non chiave non devono esistere. Consideriamo una relazione così definita: ProdottiOrdinati (CodOrdine, CodProdotto, Quantità, PercSconto) Anche in questo caso ci sono anomalie: 1) In inserimento, cioè non è possibile inserire la percentuale di sconto fino a che questa non compare in un ordine, e questo perché CodOrdine e CodProdotto non possono essere nulle). 2) In aggiornamento, cioè se varia la percentuale di sconto per una certa quantità, bisogna aggiornare tutti i record interessati. Questi problemi dipendono dal fatto che la percentuale di sconto dipende dalla quantità e non dall’articolo ordinato, quindi si ha che un attributo non chiave (PercSconto) dipende da un altro attributo non chiave (Quantità). Lo schema viene trasformato in: ProdottiOrdinati (CodOrdine, CodProdotto, Quantità, PercSconto) Sconti (Quantità, PercSconto) Riassumendo: Nello schema originario rimane la chiave primaria e tutti gli attributi non chiave dipendenti direttamente da essa. Si crea una nuova entità per ogni attributo da cui dipendono altri attributi non chiave LO STANDARD SQL Il linguaggio SQL (Structured Query Languge) è un linguaggio non procedurale adatto a creare, manipolare e interrogare le basi di dati relazionali. Il linguaggi SQL assolve alle funzioni di: 1) DDL (Data Definition Language), che prevede le istruzioni per definire la struttura delle relazioni del database. In sostanza il DDL serve a creare tabelle e vincoli. 2) DML (Data Manipulation Language), che permette la manipolazione dei dati, ossia inserimenti, cancellazioni e modifiche sulle righe, nonché le interrogazioni del databese. 3) DCL (Data Control Language), che controlla il modo in cui le operazioni vengono eseguite, gli accessi e i permessi per gli utenti autorizzati. Il linguagio SQL può essere usato in modalità a se stante (STAND ALONE) oppure in modalità linguaggio ospite (EMBEDDED), se è utilizzato all’interno di istruzioni scritte in linguaggi di programmazione come il C, C++ o Java, e che sono considerati proprio come”linguaggi ospite”. SQL non è un linguaggio “case sensitive”, quindi le istruzioni possono essere scritte indifferentemente usando caratteri maiuscoli e minuscoli. Gli identificatori usati per i nomi delle tabelle e degli attributi devono: 1) Avere lunghezza massima di 18 caratteri. 2) Iniziare con una lettera 3) Avere come unico carattere speciale il simbolo “_” (underscore). In SQL le relazioni sono tabelle, i record sono le righe e gli attributi sono le colonne. La sintassi che lega un attributo alla tabella è: <NOME TABELLA>, <NomeAttributo> Sono permessi gli operatori matematici, logici (AND, NOT, OR) relazionali. ISTRUZIONI DEL DDL DI SQL Per creare un nuovo database usiamo il comando: CREATE DATABASE <NomeDatabase> [AUTHORIZATION <Proprietario>] Il nome dell’utente proprietario può essere opzionale. Es: CREATE DATABASE <Negozio> [AUTHORIZATION <Proprietario>] Per selezionare un database abbiamo: USE <NomeDatabase> Per creare una tabella con vincoli di integrità, abbiamo la seguente sintassi: CREATE TABELLA <NomeTabella> (<Attributo1> <Tipo1> [<VincoloAttributo1>], ……………………………………………………….. (<AttributoN> <TipoN> [<VincoloAttributoN>], [<VincoloTabella>]; integrità referenziale I vincoli per un singolo attributo impostano limitazioni sui valori di un singolo attributo e possono essere impostati attraverso le seguenti clausole: NOT NULL: richiede che un valore venga necessariamente specificato, come ad esempio: Cognome CHAR(30) NOT NULL. DEFAULT: assegno all’attributo il valore predefinito in <ValoreDiDefault>, come ad esempio Pensionato BIT DEFAULT 0 CHECK (<Condizione>): serve per specificare un qualsiasi vincolo riguardante il valore di un attributo, come ad esempio: CHECK (Stipendio>1000), che impedirà che il valore di Stipendio sia inferiore a 1000. All’interno di CHECK si possono usare anche altri operatori (IN, BETWEEN, LIKE..), come ad esempio: CHECK( Stipendio IN (1500,2000,2500,3000)), significa che lo stipendio assume uno dei quattro valori in parentesi. CHECK( Stipendio BETWEEN 1500 and 3000) , significa che lo stipendio è compreso tra i due valori. CHECK( CodArticolo LIKE “Cod%”), significa che l’attributo inizia con Cod, mentre l’operatore % rappresenta una sequenza di zero o più caratteri. Vediamo un esempio completo: CREATE TABLE Azienda { CodAzienda CHAR (5) NOT NULL, RagioneSociale CHAR (30) NOT NULL, Fatturato INT (9) DEFAULT 1000000, NumeroDip INT (5), CHECK (NumeroDip BETWEEN 5 AND 200) }; Possono essere anche impostate le seguenti clausole: PRIMARY KEY (<Attributo1>,……,<AttributoN>) UNIQUE (<Attributo1>,……,<AttributoN>), indica che gli attributi dati e che non sono chiavi primarie devono essere distinti. Un esempio riassuntivo è il seguente: CREATE TABLE Azienda { CodAzienda CHAR (5) NOT NULL, RagioneSociale CHAR (30) NOT NULL, CodDip CHAR (6) NOT NULL, PRIMARY KEY (CodAzienda) }; CREATE TABLE Dipendente { CodDip CHAR (6) NOT NULL, Cognome CHAR (30) NOT NULL, Nome CHAR (20) NOT NULL, DataAssunz DATE, Livello CHAR (1) DEFAULT “6”, StipLordo DECIMAL (8,3) NOT NULL, Trattenute DECIMAL (8,3) NOT NULL, StipNetto DECIMAL (8,3) NOT NULL, PRIMARY KEY (CodDip) UNIQUE (Cognome, Nome, DataAssunz), CHECK (StipLordo > 0), CHECK (StipNetto > 0), CHECK (Stipnetto = StipLordo – Trattenute), }; Per ciò che riguarda i vincoli sulle chiavi esterne, abbiamo le seguenti clausole: FOREIGN KEY (<Attributo1>,……,<AttributoN>) REFERENCES <NomeTabella>(<Attr1>,……,<AttrN>) [[ON DELETE/ON UPDATE] CASCADE/SET NULL/SET DEFAULT/NO ACTION] Tra parentesi quadre abbiamo il tipo di politica da seguire in caso di violazione del vincolo referenziale. In particolare con l’opzione: 1) CASCADE vengono cancellate le righe corrispondenti 2) SET NULL, sono impostate a NULL le righe corrispondenti 3) SET DEFAULT, le righe corrispondenti vengono impostate al valore di default 4) NO ACTION, non viene eseguita alcuna azione ed essa è l’impostazione di default se non viene specificata la clausola ON DELETE. Al momento della modifica di un attributo interessato da un vincolo referenziale (ON UPDATE), si possono avere vari comportamenti, quindi con l’opzione: 1) CASCADE, le corrispondenti righe sono impostate con il nuovo valore 2) SET NULL, le righe sono impostate a NULL Consideriamo un esempio riassuntivo in cui vengono create tre tabelle Azienda, Dipendente, Categoria, con tutti i vincoli del caso. Avremo il seguente schema di creazione: CREATE TABLE Azienda { CodAzienda CHAR (5) RagioneSociale CHAR (30) CodAttività CHAR (4) CodDip CHAR (6) NOT NULL, NOT NULL, NOT NULL, NOT NULL, PRIMARY KEY (CodAzienda) FOREIGN KEY (CodDip) REFERENCES Dipendente (CodDip) ON DELETE SET NULL FOREIGN KEY (CodAttività) REFERENCES Categoria (CodAttività) ON UPDATE CASCADE }; CREATE TABLE Dipendente { CodDip CHAR (6) NOT NULL, Cognome CHAR (30) NOT NULL, Nome CHAR (20) NOT NULL, PRIMARY KEY (CodDip), }; CREATE TABLE Categoria { CodCategoria CHAR (4) NOT NULL, Nome CHAR (20) NOT NULL, PRIMARY KEY (Cod Categoria), }; È possibile legare agli attributi di una tabella, alcune tabelle speciali dette INDICI, che sono file contenenti le chiavi delle tabelle a cui sono associati e servono per velocizzare i processi di ricerca dei dati. Il comando di creazione è: CREATE [UNIQUE] INDEX <NomeIndice> ON <NomeTabella>(<Attributo1>,……,<AttributoN>) MODIFICARE LA STRUTTURA DI UNA TABELLA Il comando per aggiungere una colonna in una tabella è il seguente: ALTER TABLE <NomeTabella> ADD <NomeColonna1><NomeTipo> [BEFORE <NomeColonna2>]; Il comando per eliminare una colonna è: ALTER TABLE <NomeTabella> DROP COLUMN <NomeColonna>; Il comando per modificare il tipo di una colonna ma non il nome è: ALTER TABLE <NomeTabella> MODIFY (<NomeColonna><NuovoTipoColonna>) Es: ALTER TABLE Dipendente ADD DataNascita Date; ALTER TABLE Dipendente DROP COLUMN DataAssunzione; Per eliminare una intera tabella la sintassi è la seguente: DROP TABLE <NomeTabella> [RESCRICT/CASCADE/SET NULL]; RESTRICT non permette la cancellazione se la tabella è legata ad altre tabelle. CASCADE dà luogo ad una cancellazione ricorsiva in cascata di tutte le tabelle collegate. SET NULL pone come NULL tutti i valori delle chiavi interessate. Ad esempio, per cancellare la tabella Categorie, scriveremo semplicemente: DROP TABLE Categoria; infatti se scrivessimo DROP TABLE Categoria RESCRICT, l’operazione non sarebbe consentita se ci fossero valori chiave nell’attributo CodAttività della tabella Azienda che si riferiscono a record di categoria. Se scriviamo: DROP TABLE Categoria CASCADE; viene cancellata la tabella categoria e con essa tutti i riferimenti alle chiavi di Categoria presenti nell’attributo CodAttività di Azienda. Allo stesso modo si può eliminare un indice: DROP INDEX <NomeIndice>; ISTRUZIONI DEL DML DI SQL Tali comandi consentono di poter inserire, modificare e cancellare i valori delle righe delle tabelle, e visualizzare i contenuti attraverso interrogazioni. Se vogliamo inserire valori delle righe in una tabella si ha la seguente sintassi: INSERT INTO <NomeTabella> [(<Attributo1>,……,<AttributoN>)] VALUES (<Valore1>…… <ValoreN>); Es: INSERT INTO Categoria VALUES ( “C001”, “Servizi”); INSERT INTO Categoria (CodCategoria) VALUES ( “C002”); in questo caso il nome sarà NULL Per aggiornare una o più righe di una tabella si ha la seguente sintassi: UPDATE <NomeTabella> SET[(<Attributo1>= <Espressione1> ……………………………….. [(<AttributoN>= <EspressioneN> [WHERE <condizione>]; Ad esempio, per cambiare la ragione sociale dell’azienda A001, scriveremo: UPDATE Azienda SET RagioneSociale = “Nuova Elettronica 3000” WHERE CodAzienda = “A001”; Si possono anche effettuare operazioni sugli attributi, come in questo caso: UPDATE Dipendente SET StipLordo = StipLordo + 100; Per cancellare una o più righe di una tabella utilizziamo la seguente sintassi: DELETE FROM <NomeTabella> [WHERE <condizione>]; Es: per cancellare i dipendenti assunti prima del 31 Dicembre 1990, scriveremo: DELETE FROM Dipendente WHERE Data <= 31/12/1990; COMANDI PER IL REPERIMENTO DEI DATI Estrarre i dati significa effettuare un’interrogazione sul database. Il risultato è sempre una tabella e la sintassi di un’interrogazione è la seguente: SELECT [DISTINCT] <Attributo1>,……,<AttributoN> FROM <Tabella1>, <Tabella2>,……,<TabellaK> [WHERE <condizione>]; l’opzione DISTINCT significa che il risultato viene fornito privo di righe duplicate. Se vogliamo visualizzare tutti gli attributi presenti nel prodotto delle tabelle, si può usare il simbolo “*”. La condizione può essere composta da più condizioni semplici combinate con gli operatori logici AND, NOT, OR. Es: SELECT Cognome, Nome FROM Dipendente SELECT Cognome, Nome FROM Dipendente WHERE StipNetto > 2000 Per rinominare una colonna di una tabella si assegna un “alias” in questo modo: SELECT Cognome, StipNetto AS Attuale FROM Dipendente Si possono anche effettuare calcoli sugli attributi, con il risultato visualizzato in una nuova colonna. Ad esempio se vogliamo una variazione del 10% degli stipendi dei dipendenti, avremo: SELECT Cognome, Nome, StipNetto*1,1 AS Nuovo FROM Dipendente Una menzione speciale merita la clausola NULL, che viene utilizzata per indicare diverse situazioni. Infatti un valore è null quando esso non esiste ma anche quando esiste ed è sconosciuto. Tale valore non compare nei campi di una tabella ma è rappresentato da un campo vuoto. Nelle interrogazioni si ricorre ai predicati IS NULL e IS NOT NULL. Quindi per elencare tutti i clienti che non hanno numero di telefono, scriveremo: SELECT CodCli, Cognome, Nome FROM Clienti WHERE Telefono IS NULL OPERAZIONI RELAZIONALI IN SQL L’operazione di SELEZIONE vista anche nell’algebra relazionale (σ), viene utilizzata mediante la clausola WHERE. Ad esempio se vogliamo l’elenco di tutti i dipendenti con stipendio minore o uguale a 1000€, scriveremo. SELECT * FROM Dipendenti WHERE StipNetto <= 1000; L’operazione di PROIEZIONE (π), permette di ottenere una tabella con solo gli attributi che sono specificati dopo SELECT, come ad esempio: SELECT Cognome, Nome FROM Dipendenti L’operazione di CONGIUNZIONE unisce due o più tabelle attraverso le chiavi. In SQL esistono vari tipi di congiunzione o JOIN: 1) JOIN o CROSS JOIN, che equivale al prodotto delle relazioni e contenente tutte le combinazioni possibili tra i record delle due tabelle. La sintassi è: <Tabella1> [CROSS] JOIN <Tabella2> Es: SELECT Cognome, Studente.NomeClasse, Classe.NomeClasse FROM Studente JOIN Classe 2) INNER JOIN, che visualizza solo le combinazioni dei record della prima tabella che sono in corrispondenza nella seconda tabella per gli attributi comuni. La sintassi è: <Tabella1> INNER JOIN <Tabella2> ON <Condizione> Es: SELECT Cognome, Studente.NomeClasse, Classe.NomeClasse FROM Studente INNER JOIN Classe ON Studente.NomeClasse = Classe.NomeClasse In alternativa vale anche l’interrogazione che usa SELECT e che è di gran lunga più utilizzata e cioè: Es: SELECT Cognome, Studente.NomeClasse, Classe.NomeClasse FROM Studente, Classe WHERE Studente.NomeClasse = Classe.NomeClasse 3) LEFT JOIN o join sinistro, visualizza i record della tabella a sinistra della sintassi e quelle della tabella a destra che hanno un valore corrispondente per l’attributo comune. La sintassi è la seguente: <Tabella1> LEFT JOIN <Tabella2> ON <Condizione> 4) RIGHT JOIN o join destro, visualizza i record della tabella a destra della sintassi e quelle della tabella a sinistra che hanno un valore corrispondente per l’attributo comune. La sintassi è la seguente: <Tabella1> RIGHT JOIN <Tabella2> ON <Condizione> 5) SELF JOIN, che si utilizza per effettuare interrogazioni con concatenazioni sulla stessa tabella, con l’utilizzo degli alias. Ad esempio, se abbiamo l’associazione GenitoreDi sulla stessa entità Persona Persona (CodPers, Cognome, Nome) GenitoreDi(CodPers1, CodPers2) e vogliamo avere una tabella risultato con il cognome e il nome delle persone accanto al cognome e il nome dei genitori, dovremo scrivere: SELECT Tab1.Cognome, Tab1.Nome, Tab2.Cognome, Tab2.Nome FROM Persona AS Tab1, Persona AS Tab2 WHERE Tab1.CodPers1 = Tab2.CodPers2; UNIONE, INTERSEZIONE E DIFFERENZA Consideriamo le seguenti relazioni: Regista (CodRegista, Cognome, Nome) Attore (CodAttore, Cognome, Nome) Per ottenere i registi che sono stati anche attori avremo: (SELECT Cognome, Nome FROM Regista) INTERSECT (SELECT Cognome, Nome FROM Attore) n.b: le parentesi sono obbligatorie! Per ottenere i registi che non sono mai stati attori, scriveremo: (SELECT Cognome, Nome FROM Regista) EXCEPT (SELECT Cognome, Nome FROM Attore) Per ottenere tutti I registi e tutti gli attori, avremo: (SELECT Cognome, Nome FROM Regista) UNION (SELECT Cognome, Nome FROM Attore) INTERROGAZIONI PARAMETRICHE Le interrogazioni parametriche sono molto utili quando bisogna sfruttarle per diversi valori del parametro. Infatti consideriamo la query seguente: SELECT * FROM Clienti WHERE Nome = “Rossi”; Se volessimo visualizzare i dati relativi al cliente Bianchi dovremmo riscrivere la query. Con l’uso delle query parametriche, l’interrogazione viene riscritta nel seguente modo: SELECT * FROM Clienti WHERE Nome = [inserisci il nome] In questo modo, prima di essere eseguita, l’interrogazione chiederà di inserire un valore per il parametro specificato. FUNZIONI DI AGGREGAZIONE Tali funzioni vengono usate per effettuare conteggi, somme, medie, e si applicano ad una colonna di una tabella. La sintassi è la seguente: <FunzioneDiAggregazione> ([DISTINCT] <Attributo>) Le principali funzioni sono: 1) COUNT: conteggia il numero di elementi della colonna specificata in <Attributo>. Se al posto dell’attributo troviamo il simbolo *, la funzione COUNT(*) calcola il numero delle righe di tutta la tabella comprese quelle contenenti il valore NULL. n.b : la clausola DISTINCT non può essere usata con la funzione COUNT(*). 2) MIN, MAX: restituiscono il valore minimo e massimo della colonna specificata in <Attributo>. 3) SUM: restituisce la somma degli elementi della colonna specificata in <Attributo>. 4) AVG: restituisce la media aritmetica degli elementi della colonna specificata in <Attributo>. Esempi: data la tabella: Dipendente (CodDip, Cognome, Nome, Livello, DataStip, Stip) SELECT COUNT (Stip) FROM Dipendente WHERE Stip > 2000 calcola il numero di dipendenti che hanno lo stipendio maggiore di 2000€ SELECT SUM(Stip) FROM Dipendente calcola la somma degli stipendi SELECT MAX(Stip) FROM Dipendente calcola il valore massimo degli stipendi SELECT AVG(Stip) FROM Dipendente calcola il valore medio degli stipendi ORDINAMENTI Spesso è necessario avere degli ordinamenti sulle righe di una tabella risultato di una query. La sintassi è la seguente: ORDER BY <Attributo1> [ASC/DESC],…., Es: SELECT * FROM Dipendenti ORDER BY Cognome, Nome RAGGRUPPAMENTI La clausola di raggruppamento ha la seguente sintassi: GROUP BY <Attributo1> [HAVING <Condizione>] Es: per raggruppare i dipendenti in base al loro livello e sapere lo stipendio medio per livello, si può scrivere: SELECT Livello, AVG (Stip) FROM Dipendente GROUP BY Livello INTERROGAZIONI ANNIDATE Questi tipi di interrogazioni consistono in più comandi di tipo SELECT annidati in sottointerrogazioni, di cui troviamo la query principale individuata dal primo SELECT, e la query secondaria o interna che è individuata dal secondo SELECT delimitato da parentesi tonde. La sintassi è la seguente: SELECT <ListaAttributi> FROM <ListaTabelle> AS <NomeTabellaDerivata> Consideriamo il seguente esempio e siano date le seguenti tabelle: Laboratorio (CodLab, NumPosti, NomeLab) Classe (CodClasse, NumPosti) Utilizza ( CodLab, CodClasse) Vogliamo conoscere il nome dei laboratori usati dalla classe “A45”. L’interrogazione sarà: SELECT NomeLab query esterna FROM Laboratorio, (SELECT CodLab FROM Utilizza query interna WHERE CodClasse = “A45”) AS Lab WHERE Lab.CodLab = Laboratorio.CodLab; In un processo di interrogazioni annidate, spesso è utile conservare le tabelle risultato delle sottointerrogazioni. Per far questo basta far precedere il comando SELECT dal comando CREATE TABLE seguito dal nome da assegnare alla nuova tabella. Nelle clausole WHERE delle sottointerrogazioni è possibile utilizzare alcuni predicati per effettuare ricerche sui valori di attributi che soddisfano proprietà di appartenenza a insiemi di valori. I predicati sono: ANY e ALL che hanno la seguente sintassi: SELECT <ListaAttributi> FROM <ListaTabelle> WHERE <Attributo> ANY/ALL (<Sottoquery>) Il predicato ANY significa che la condizione della clausola WHERE è vera se il valore di <Attributo> compare in almeno uno dei valori forniti dalla sottoquery. Il predicato ALL significa che la condizione di WHERE è vera se <Attributo> compare in tutti quelli restituiti dalla sottoquery. Es: Dipendente (CodDip, Nome, Cognome, Stip) Stipendio (CodNazione, NomeNazione, Continente, StipMedio) Se vogliamo sapere quali sono i dipendenti che hanno lo stipendio superiore ad almeno uno degli stipendi medi delle nazioni europee, scriveremo: SELECT Cognome, Nome FROM Dipendente WHERE Stip > ANY (SELECT DISTINCT StipMedio FROM Stipendio WHERE Continente = “Europa”); Se vogliamo invece sapere quali sono i dipendenti che hanno lo stipendio superiore a tutti degli stipendi medi delle nazioni europee, scriveremo: SELECT Cognome, Nome FROM Dipendente WHERE Stip > ALL (SELECT DISTINCT StipMedio FROM Stipendio WHERE Continente = “Europa”); I predicati IN / NOT IN vengono utilizzati: 1) IN quando la condizione di WHERE è vera se il valore dell’attributo appartiene all’insieme dei valori forniti dalla sottoquery. 2) NOT IN quando la condizione di WHERE è vera se il valore dell’attributo non appartiene all’insieme dei valori forniti dalla sottoquery. Es: consideriamo le tabelle seguenti: Zoo (CodAnimale, Nome, CodRazza, DataArrivo) Razza ( CodRazza, Descrizione, Nazione, Continente, SpecieProtetta) Se vogliamo conoscere quali sono gli animali dello zoo originari dell’Africa, scriveremo: SELECT COUNT (CodAnimale) FROM Zoo WHERE CodRazza IN ( SELECT CodRazza FROM Razza WHERE Continente = “Africa”); Se vogliamo sapere quanti sono gli animali dello zoo che non sono specie protette, avremo: SELECT COUNT (CodAnimale) FROM Zoo WHERE CodRazza NOT IN ( SELECT CodRazza FROM Razza WHERE SpecieProtetta = “1); I predicati EXIST / NOT EXIST hanno il significato che la condizione di WHERE è vera se la sottoquery produce una tabella non vuota nel caso di exist e non vuota nel caso di not exist. Es: se abbiamo le seguenti tabelle: Cliente ( CodCli, Nome, Cognome, Telefono) HaRichiesto (CodCli, CodViaggio) Viaggio (CodViaggio, Destinazione, Prezzo, NumPersone) e vogliamo sapere quali sono i clienti che hanno richiesto di viaggiare, scriveremo: SELECT * FROM Cliente AS C WHERE EXIST ( SELECT * FROM HaRichiesto AS H WHERE C.CodCli = H.CodCli); ISTRUZIONI DEL DCL DI SQL Mediante tali istruzioni è possibile impostare le politiche relative alla sicurezza dei dati, in materia di guasti hardware e software, sicurezza da accessi non autorizzati. Per evitare queste eventualità è necessario stabilire i cosiddetti DIRITTI DI ACCESSO e stabilire le VISTE, cioè le modalità con le quali gli utenti possono vedere la base di dati. Per quanto riguarda i diritti di accesso, l’amministratore del database può assegnare diversi diritti di accesso agli altri utenti dello stesso, per consentire a questi di interagire con altre tabelle. Il comando usato è GRANT. Es: GRANT SELECT ON Tabella TO (Rossi, Bianchi) GRANT INSERT; UPDATE (Attributo) ON Tabella TO (Rossi, Bianchi) I permessi di accesso possono essere revocati tramite il comando REVOKE. Per quanto riguarda le VISTE, diciamo che esse non sono fisicamente memorizzate nel database, ma definite logicamente. La sintassi è: CREATE VIEW <NomeVista> AS <Query> Es: CREATE VIEW DaOrdinare AS SELECT * FROM Accessorio WHERE Quantità = 0; Questa vista è molto utile ad esempio ad un magazziniere per visualizzare gli accessori che devono essere ordinati, poiché terminati in magazzino. Le viste sono considerate come uno strumento di protezione dei dati. Per eliminare una vista si utilizza il comando DROP VIEW. Sulle viste è possibile utilizzare il comando GRANT.