Basi di Dati (Modelli e linguaggi di interrogazione)
 9788838666001

Citation preview

Paolo Atzeni S t e f a n o Ceri Stefano Paraboschi Riccardo Torlone

Basi di dati Modelli e linguaggi di interrogazione Terza

edizione

McGraw-Hill

Paolo Atzeni S t e f a n o Ceri Stefano Paraboschi Riccardo Torlone

Basi di dati Modelli e linguaggi di interrogazione

'aolo Atzeni è professore

ordinario di Basi di dati presso 3 facoltà di Ingegneria iell'Università Roma Tre.

•tefano Ceri è professore

)rdinario di Basi di dati presso a facoltà di Ingegneria iell'informazione del Politecnico li Milano.

befano Paraboschi è

Il testo si rivolge agli studenti di basi di dati delle facoltà di Ingegneria, di Scienze dell'informazione e di Economia, ma anche ai professionisti del settore informatico come utenti avanzati e progettisti di applicazioni. Questa terza edizione presenta importanti novità rispetto alla precedente ed è il risultato di u n lavoro di aggiornamento e integrazione in considerazione sia dei continui progressi dei linguaggi e della tecnologia per la gestione dei dati sia delle rinnovate esigenze dei corsi di laurea. Anzit utto è stato completato il percorso della progettazione delle basi di dati con l'inserimento di u n nuovo capitolo relativo alla progettazione fisica. Inoltre, il capitolo relativo alla progettazione concettuale è stato ampliato attraverso l'introduzione del concetto di "pattern". Per quanto concerne gli esempi di sistemi, è stata aggiunta un'appendice dedicata a Postgres, scelto come rappresentante per l'illustrazione dei sistemi "open source" per la sua flessibilità e il supporto naturale a tutti i servizi che caratterizzano un D B M S ; inoltre sono state aggiornate le appendici dedicate a Microsoft Access e D B 2 Universal Database. Per concludere sono stati inseriti numerosi esercizi di fine capitolo per supportare lo studente nell'apprendimento.

>rofessore ordinario presso a facoltà di Ingegneria iell'Università di Bergamo.

Riccardo Torlone è professore >rdinario presso la facoltà

ii Ingegneria dell'Università tome Tre.

All'indirizzo web www.ateneonline.it/atzeni sono disponibili materiali di supporto al testo: per i docenti, lucidi in formato PowerPoint; per gli studenti, le soluzioni di tutt esercizi presentati nel testo e un set di esercizi aggiuntivi relativa soluzione. ISBN 978-88-386-6

£ 3 5 , 0 0 (i.i.)



www.mcgraw-hill.it



www.ateneonline.it

9

7 8 8 8 3 8 66é

Paolo Atzeni Stefano Ceri Stefano Paraboschi Riccardo Torlone

Basi di dati

Modelli e linguaggi di interrogazione Terza edizione

McGraw-Hill Milano

• New York • Sari Francisco • Washington D.C. • Auckland Bogotá • Lisboa • London • Madrid • Mexico City • Montreal New Delhi • San Juan • Singapore • Sydney • Tokyo • Toronto

Copyright © 2009, 2006, 2002 The McGraw-Hill Companies, srl Publishing Group Italia via Ripamonti, 89 - 20139 Milano

McGraw-Hill A Division of The McGraw-Hill

Companies

1 diritti di traduzione, di riproduzione, di memorizzazione elettronica e di adattamento totale e parziale con qualsiasi mezzo (compresi i microfilm e le copie fotostatiche) sono riservati per tutti i Paesi. Date le caratteristiche intrinseche di Internet, l'Editore non è responsabile per eventuali variazioni negli indirizzi e nei contenuti dei siti Internet riportati. Nomi e marchi citati nel testo sono generalmente depositati o registrati dalle rispettive case produttrici. Le fotocopie per uso personale del lettore possono essere effettuate nei limiti del 15% di ciascun volume/fascicolo di periodico dietro pagamento alla SIAE del compenso previsto dall'art. 68, commi 4 e 5, della legge 22 aprile 1941 n. 633. Le riproduzioni effettuate per finalità di carattere professionale, economico o commerciale o comunque per uso diverso da quello personale possono essere effettuate a seguito di specifica autorizzazione rilasciata da AIDRO, Corso di Porta Romana 108, 20122 Milano, e-mail [email protected] e sito web www.aidro.org.

Editor: Paolo Roncoroni Produzione: Donatella Giuliani Impaginazione: CompoMat S.r.l., Configni (RI) Grafica di copertina: Editta Gelsomini Stampa: Arti Grafiche Battaia, Zibido San Giacomo (MI)

ISBN 978-88-386-6600-1 Printed in Italy 123456789B AT VER32109

Indice breve

1

Introduzione

Parte Prima

1

Basi di dati relazionali: modello e linguaggi

2

II modello relazionale

17

3

Algebra e calcolo relazionale

47

4

SQL: concetti base

95

5

SQL: caratteristiche evolute

157

6

SQL per le applicazioni

179

Parte Seconda

Progettazione di basi di dati

7

Metodologie e modelli per il progetto

207

8

La progettazione concettuale

251

9

La progettazione logica

293

10 La progettazione fisica

339

11 La normalizzazione

361

A

Microsoft Access

393

B

DB2 Universal Database

415

C

DBMS open source: Postgres

437

Indice

Prefazione

xiii

Ringraziamenti dell'Editore

xvii

1

Introduzione 1.1 Sistemi informativi, informazioni e dati 1.2 Basi di dati e sistemi di gestione di basi di dati 1.3 Modelli dei dati 1.3.1 Schemi e istanze 1.3.2 Livelli di astrazione nei DBMS 1.3.3 Indipendenza dei dati 1.4 Linguaggi e utenti delle basi di dati 1.4.1 Linguaggi per basi di dati 1.4.2 Utenti e progettisti 1.5 Vantaggi e svantaggi dei DBMS Note bibliografiche

Parte prima 2

Basi di dati relazionali: modello e linguaggi

II modello relazionale 2.1 II modello relazionale: strutture 2.1.1 Modelli logici nei sistemi di basi di dati 2.1.2 Relazioni e tabelle 2.1.3 Relazioni con attributi 2.1.4 Relazioni e basi di dati 2.1.5 Informazione incompleta e valori nulli 2.2 Vincoli di integrità 2.2.1 Vincoli di tupla 2.2.2 Chiavi 2.2.3 Chiavi e valori nulli 2.2.4 Vincoli di integrità referenziale 2.3 Conclusioni Note bibliografiche Esercizi

1 1 3 6 8 8 9 10 10 11 13 14 15 17 17 17 18 20 23 28 31 33 33 36 37 41 42 ^2

3

Algebra e calcolo relazionale 3.1 Algebra relazionale 3.1.1 Unione, intersezione, differenza 3.1.2 Ridenominazione 3.1.3 Selezione 3.1.4 Proiezione 3.1.5 Join 3.1.6 Interrogazioni in algebra relazionale 3.1.7 Equivalenza di espressioni algebriche 3.1.8 Algebra con valori nulli 3.1.9 Viste 3.2 Calcolo relazionale 3.2.1 Calcolo relazionale su domini 3.2.2 Pregi e difetti del calcolo su domini 3.2.3 Calcolo su tuple con dichiarazioni di range 3.3 Datalog Note bibliografiche Esercizi

47 48 48 49 51 53 55 63 67 70 72 74 75 80 82 85 89 89

4

SQL: concetti base 4.1 II linguaggio SQL e gli standard 4.2 Definizione dei dati in SQL 4.2.1 I domini elementari 4.2.2 Definizione di schema 4.2.3 Definizione delle tabelle 4.2.4 Definizione dei domini 4.2.5 Specifica di valori di default 4.2.6 Vincoli intrarelazionali 4.2.7 Vincoli interrelazionali 4.2.8 Modifica degli schemi 4.2.9 Cataloghi relazionali 4.3 Interrogazioni in SQL 4.3.1 Dichiaratività di SQL 4.3.2 Interrogazioni semplici 4.3.3 Operatori aggregati 4.3.4 Interrogazioni con raggruppamento 4.3.5 Interrogazioni di tipo insiemistico 4.3.6 Interrogazioni nidificate 4.4 Modifica dei dati in SQL 4.4.1 Inserimento 4.4.2 Cancellazione 4.4.3 Modifica 4.5 Esempi riepilogativi Note bibliografiche Esercizi

95 95 98 98 101 102 103 103 104 106 108 110 112 112 113 127 130 134 137 144 144 145 147 148 151 151

5

SQL: caratteristiche evolute 5.1 Caratteristiche evolute di definizione dei dati 5.1.1 Vincoli di integrità generici 5.1.2 Asserzioni 5.1.3 Viste 5.1.4 Le viste per la scrittura di interrogazioni 5.1.5 Esempi riepilogativi d'uso delle viste 5.1.6 Viste ricorsive in SQL-3 5.2 Funzioni scalari 5.2.1 Famiglie di funzioni 5.2.2 Funzioni condizionali 5.3 Controllo dell'accesso 5.3.1 Risorse e privilegi 5.3.2 Comandi per concedere e revocare privilegi 5.3.3 I ruoli in SQL-3 5.4 Transazioni Note bibliografiche Esercizi

157 157 157 158 160 161 163 164 165 165 166 168 169 170 171 172 174 175

6

SQL 6.1 6.2 6.3

179 180 182 184 187 190 192 194 198 201 202

6.4

per le applicazioni Procedure Trigger SQL Embedded 6.3.1 Cursori 6.3.2 SQL dinamico Cali Level Interface (CLI) 6.4.1 ODBC e soluzioni proprietarie Microsoft 6.4.2 Java Database Connectivity (JDBC) Note bibliografiche Esercizi

Parte seconda 7

Progettazione di basi di dati

Metodologie e modelli per il progetto 7.1 Introduzione alla progettazione 7.1.1 II ciclo di vita dei sistemi informativi 7.1.2 Metodologie di progettazione e basi di dati 7.2 II modello Entità-Relazione 7.2.1 I costrutti principali del modello 7.2.2 Altri costrutti del modello 7.2.3 Panoramica finale sul Modello E-R 7.3 Documentazione di schemi E-R 7.3.1 Regole aziendali 7.3.2 Tecniche di documentazione 7.4 Modellazione dei dati in UML

205 207 207 207 209 212 214 220 228 230 230 232 234

7.4.1 Panoramica su UML 7.4.2 Rappresentazione di dati con i diagrammi delle classi Note bibliografiche Esercizi

235 236 244 245

8

La progettazione concettuale 8.1 La raccolta e l'analisi dei requisiti 8.2 Rappresentazione concettuale di dati 8.2.1 Criteri generali di rappresentazione 8.2.2 Pattern di progetto 8.3 Strategie di progetto 8.3.1 Strategia top-down 8.3.2 Strategia bottom-up 8.3.3 Strategia inside-out 8.3.4 Strategia mista 8.4 Qualità di uno schema concettuale 8.5 Una metodologia generale 8.6 Un esempio di progettazione concettuale 8.7 Strumenti CASE per la progettazione di basi di dati Note bibliografiche Esercizi

251 251 257 257 258 267 267 268 270 271 272 273 275 279 281 282

9

La progettazione logica 9.1 Fasi della progettazione logica 9.2 Analisi delle prestazioni su schemi E-R 9.3 Ristrutturazione di schemi E-R 9.3.1 Analisi delle ridondanze 9.3.2 Eliminazione delle generalizzazioni 9.3.3 Partizionamento/accorpamento di concetti 9.3.4 Scelta degli identificatori principali 9.4 Traduzione verso il modello relazionale 9.4.1 Entità e associazioni molti a molti 9.4.2 Associazioni uno a molti 9.4.3 Entità con identificatore esterno 9.4.4 Associazioni uno a uno 9.4.5 Traduzioni di schemi complessi 9.4.6 Tabelle riassuntive 9.4.7 Documentazione di schemi logici 9.5 Un esempio di progettazione logica 9.5.1 Fase di ristrutturazione 9.5.2 Traduzione verso il relazionale 9.6 Progettazione logica con gli strumenti CASE Note bibliografiche Esercizi

293 293 295 298 299 302 306 310 311 311 314 315 316 317 319 319 323 324 328 329 331 331

10 La progettazione fisica 10.1 Organizzazione fìsica nei DBMS relazionali 10.1.1 Caratteristiche della memoria secondaria 10.1.2 Organizzazione fisica delle relazioni 10.1.3 Indici relazionali 10.2 Progettazione fisica di una base di dati Note bibliografiche Esercizi

339 339 340 342 345 352 357 357

11 La normalizzazione 11.1 Ridondanze e anomalie 11.2 Dipendenze funzionali 11.3 Forma normale di Boyce e Codd 11.3.1 Definizione di forma normale di Boyce e Codd 11.3.2 Decomposizione in forma normale di Boyce e Codd 11.4 Proprietà delle decomposizioni 11.4.1 Decomposizione senza perdita 11.4.2 Conservazione delle dipendenze 11.4.3 Qualità delle decomposizioni 11.5 Terza forma normale 11.5.1 Limitazioni della forma normale di Boyce e Codd 11.5.2 Definizione di terza forma normale 11.5.3 Decomposizione in terza forma normale 11.5.4 Altre forme normali 11.5.5 Normalizzazione e scelta degli attributi 11.6 Teoria delle dipendenze e normalizzazione 11.6.1 Implicazione di dipendenze funzionali 11.6.2 Coperture di insiemi di dipendenze funzionali 11.6.3 Sintesi di schemi in terza forma normale 11.7 Progettazione di basi di dati e normalizzazione 11.7.1 Verifiche di normalizzazione su entità 11.7.2 Verifiche di normalizzazione su associazioni 11.7.3 Ulteriori decomposizioni di associazioni 11.7.4 Ulteriori decomposizioni di schemi concettuali Note bibliografiche Esercizi

361 361 363 365 365 366 367 367 370 371 372 372 372 373 374 375 377 377 379 380 382 383 385 386 388 389 389

A

393 393 394 399 401 402 403 409 411

Microsoft Access A.l Caratteristiche del sistema A.2 La definizione delle tabelle A.2.1 Specifica dei cammini dijoin A.2.2 Popolamento delle tabelle A.3 La definizione di query A.3.1 Query By Example A.3.2 L'interprete SQL A.4 Maschere e report

A.5

La definizione di macro

413

6

DB2 Universal Database B.l Caratteristiche generali di DB2 B.l.l Versioni del sistema B. 1.2 Istanze e schemi di DB 2 B.1.3 Interazione con DB2 B.2 Gestione di una base di dati con DB2 B.2.1 Strumenti per la gestione interattiva B.2.2 Applicazioni B.3 Funzionalità avanzate di DB2 B.3.1 Dati complessi B.3.2 Extender B.3.3 Tipi utente B.3.4 Funzioni utente

415 416 416 417 417 418 418 425 429 429 430 431 432

C

DBMS open source: Postgres C.l Caratteristiche del sistema C.2 Installazione e prima configurazione C.2.1 Interazione testuale: psql C.2.2 Interazione grafica: pgAdmin C.3 Costruzione di una base di dati d'esempio C.4 Supporto dello standard SQL C.5 Funzionalità evolute C.5.1 Estensione procedurale C.5.2 Integrazione con altri linguaggi di programmazione C.5.3 Gestione di trigger

437 438 439 440 441 444 444 445 445 448 449

Bibliografia

451

Indice analitico

455

Prefazione

Questo testo presenta i concetti fondamentali sulle basi di dati, sui linguaggi di interrogazione e di gestione, e sulle tecniche e sui metodi di progettazione. Esso nasce da una lunga esperienza di insegnamento in corsi riguardanti le basi di dati, in ambito sia universitario sia industriale e applicativo, e pertanto si rivolge al pubblico degli studenti (in particolare di Ingegneria e di Scienze dell'informazione o Informatica) e a quello dei professionisti (utenti e progettisti di applicazioni). Questa nuova edizione tiene conto anche di un'estesa esperienza di attuazione del Nuovo Ordinamento didattico universitario, avviato intorno al 2000 e caratterizzato dalla presenza di un primo modulo di basi di dati, al secondo o al terzo anno di corso.

Contenuti Il libro si articola in due parti: Basi di dati relazionali, modello e linguaggi. Vengono presentate le caratteristiche fondamentali delle basi di dati che risultano di interesse per gli utenti e i programmatori. In particolare, si illustrano il modello relazionale e i relativi linguaggi, in modo preciso e concreto, con riferimento sia alle definizioni formali (del modello, dell'algebra e del calcolo) sia ai sistemi esistenti (con riferimento soprattutto al linguaggio SQL). Progettazione di basi di dati. Viene illustrato ed esemplificato il processo di progettazione concettuale, logica e fisica delle basi di dati relazionali, che permette, partendo dai requisiti di utente, di arrivare a produrre strutture di basi di dati di buona qualità. Infine, nelle appendici vengono presentate le caratteristiche salienti di alcuni sistemi relazionali molto diffusi. Ciascun capitolo è corredato di numerosi esempi ed esercizi, nonché di una nota bibliografica che indica le fonti per possibili approfondimenti, elencate poi globalmente alla fine del volume.

Utilizzo didattico Nell'esperienza degli Autori, gli argomenti trattati in questo volume vengono svolti in modo completo in un tipico primo corso di basi di dati, corrisponden-

te cioè a un modulo da 5-6 crediti (circa 30 ore di lezione e 20 di esercitazione). A essi è opportuno associare un'ampia attività pratica, in particolare lo svolgimento di un progetto di un piccolo sistema informativo che includa una base di dati. Informazioni utili circa l'organizzazione di alcuni D B M S relazionali sono disponibili in appendice. Il presente testo ha una naturale continuazione nel testo "Basi di dati: architetture e linee di evoluzione" [5], che può essere utilizzato per un secondo modulo più avanzato oppure, insieme a questo, per un eventuale corso di 10-12 crediti. Tale testo, cui nel seguito faremo spesso riferimento come "il secondo volume", copre i seguenti argomenti. Tecnologia delle basi di dati. Vengono descritte le caratteristiche interne dei sistemi di basi di dati in rapporto all'architettura hardware e software del sistema informativo, in modo da comprenderne il funzionamento e sfruttarne appieno le potenzialità. Evoluzione dei modelli e dei linguaggi per basi di dati. Vengono illustrate le moderne varianti rispetto al modello e al linguaggio relazionale, focalizzandosi sulle basi di dati a oggetti, sulla gestione di dati XML, sulle basi di dati attive e sulla gestione di stream di dati. Architetture evolute per basi di dati. Vengono illustrate le principali architetture dei sistemi informativi moderni, focalizzandosi sulla distribuzione dei dati, sulla integrazione con il World Wide Web e sui sistemi per l'analisi dei dati e il supporto alle decisioni.

Esperienze e ringraziamenti L'organizzazione di questo testo e i suoi contenuti riflettono l'esperienza didattica degli Autori, che hanno tenuto per molti anni il corso universitario di Basi di dati e hanno svolto in altri contesti corsi sugli stessi temi. In particolare, Paolo Atzeni ha svolto in passato il corso di Basi di dati presso la facoltà di Ingegneria dell'Università di Roma "La Sapienza" e prima ancora presso l'Università di Toronto, tiene ora i corsi di Basi di dati, di Tecnologia delle basi di dati e di Sistemi informativi presso la facoltà di Ingegneria dell'Università Roma Tre. Stefano Ceri tiene i corsi di Basi di dati 1, Basi di dati 2 e Argomenti avanzati di sistemi informativi presso la facoltà di Ingegneria dell'informazione del Politecnico di Milano. Ha inoltre tenuto varie edizioni del corso "Principles of Distributed Databases" presso l'Università di Stanford. Stefano Paraboschi tiene corsi di Basi di dati e Sistemi informativi presso le facoltà di Ingegneria dell'Università di Bergamo e del Politecnico di Milano. Riccardo Torlone tiene corsi di Basi di dati presso la facoltà di Ingegneria dell'Università Roma Tre. Alla concezione e alla revisione di questo testo hanno contribuito, direttamente o indirettamente, anche attraverso discussioni sui contenuti didattici dei corsi o suggerimenti di vario tipo, numerosi colleghi, collaboratori e lettori. Citiamo, fra gli altri, Maristella Agosti, Giorgio Ausiello, Elena Baralis, Giovanni Barone, Carlo Batini, Giampio Bracchi, Daniele Braga, Francesca Bugiotti, Luca Cabib-

bo, Alessandro Campi, Paolo De Nictolis, Giuseppe Di Battista, Angelo Foglietta, Piero Fraternali, Maurizio Lenzerini, Gianni Mecca, Paolo Merialdo, Barbara Pernici, Silvio Salza, Pierangela Samarati, Fabio Schreiber, Giuseppe Sindoni, Elena Tabet e Letizia Tanca. A ciascuno di essi, nonché a coloro che abbiamo dimenticato, va il nostro più sincero ringraziamento.

Nota di edizione Questa nuova edizione esce a quindici anni di distanza dalla pubblicazione del volume: "Basi di dati: concetti, linguaggi e architetture", che ha visto la sua seconda edizione e un'edizione internazionale nel 1999. Da allora, abbiamo suddiviso il materiale in due volumi, le cui prime edizioni sono uscite nel 2003 e 2004, e le seconde edizioni nel 2006 e 2007. Presentiamo ora la terza edizione del primo volume e prevediamo un aggiornamento del secondo volume nel 2010. Il costante lavoro di aggiornamento e integrazione di queste opere tiene conto del continuo progresso dei linguaggi e della tecnologia per la gestione dei dati (che, per esempio, nell'ultimo decennio ha visto un'esplosione nelle applicazioni su Internet), e di commenti sull'uso del testo e di suggerimenti sui nuovi requisiti didattici espressi dai colleghi docenti, docenti di corsi di Basi di dati offerti dalle facoltà di Ingegneria e di Scienze dell'informazione o Informatica, raccolti da McGraw-Hill e analizzati con attenzione dagli autori. Nell'evoluzione dalla prima alla seconda edizione avevamo già operato numerose modifiche, aggiornando i capitoli relativi a SQL, tenendo conto dell'evoluzione dello standard SQL-3, collegando la progettazione concettuale alla progettazione UML ed estendendo il capitolo sulla normalizzazione. Rispetto alla precedente, questa terza edizione presenta le seguenti novità. • È stato aggiunto un nuovo capitolo relativo alla progettazione fisica dei dati, completando il percorso che va dalla progettazione concettuale alla progettazione logica alla progettazione fisica. Come prerequisito al passo progettuale è stato necessario aggiungere alcuni cenni alle strutture fisiche dei dati, in parziale sovrapposizione con gli argomenti iniziali del "secondo volume". In tal modo, gli aspetti architetturali di una base di dati, che sono tipicamente a cavallo tra un primo e un secondo corso, possono essere studiati in continuità con gli aspetti progettuali nell'ambito del primo corso e poi ripresi e ampliati in un approfondimento legato alle tecnologie nell'ambito del secondo corso. • E stato ampliato il capitolo relativo alla progettazione concettuale, introducendo il concetto di "pattern" e poi descrivendo i pattern di uso più comune (tra essi, per esempio, la reificazione e la storicizzazione). • L'appendice è stata ampliata, aggiungendo la descrizione di Post gres, scelto come rappresentante dei sistemi "open source" che stanno sempre più diffondendosi, soprattutto tra gli studenti universitari; le descrizioni dei prodotti Microsoft Access e DB2 Universal Database sono state aggiornate. Inoltre, tutto il materiale è stato rivisto e aggiornato, e al termine di ciascun capitolo sono stati aggiunti numerosi esercizi.

Materiale aggiuntivo Materiale didattico di supporto al libro è disponibile ai siti: http ://www.ateneonline.it/atzeni http ://www.dia.uniroma3.it/librobd In particolare, per gli studenti sono disponibili le soluzioni di tutti gli esercizi presenti nel testo, esercizi aggiuntivi e l'Appendice A dell'edizione del 1996 (relativa al modello reticolare e omessa nelle edizioni successive). Per i docenti che utilizzano il testo sono disponibili, oltre ai materiali presenti nell'area studenti, i lucidi che coprono in modo completo gli undici capitoli della presente edizione. Per eventuali segnalazioni di errori e altri suggerimenti, gli Autori possono essere contattati attraverso i siti stessi.

Ringraziamenti dell'Editore

L'Editore ringrazia i revisori che con le loro preziose indicazioni hanno contribuito alla realizzazione della terza edizione di Basi di dati. Modelli e linguaggi di interrogazione: Alessandro Aldini, Università degli Studi di Urbino "Carlo Bo" Paolo Baldan, Università degli Studi di Padova Elena Baralis, Politecnico di Torino Stefania Costantini, Università degli Studi dell 'Aquila Nicoletta Dessi, Università degli Studi di Cagliari Paolino Di Felice, Università degli Studi dell'Aquila Andrea Formisano, Università degli Studi di Perugia Danilo Montesi, Università di Bologna Adriano Peron, Università degli Studi di Napoli Federico II Giuseppe Polese, Università degli Studi di Salerno Domenico Ursino, Università degli Studi Mediterranea di Reggio

Calabria

W

u

Introduzion

Le attività di raccolta, organizzazione e conservazione dei dati costituiscono uno dei principali compiti dei sistemi informatici. Gli elenchi di utenze telefoniche, le quotazioni delle azioni nei mercati telematici internazionali, i saldi dei conti correnti bancari o le disponibilità di spesa associate alle carte di credito, l'elenco degli iscritti a una facoltà universitaria e gli esiti dei loro esami sono esempi di dati indispensabili a gestire alcune attività umane. I sistemi informatici garantiscono che questi dati vengano conservati in modo permanente su dispositivi per la loro memorizzazione, aggiornati per riflettere rapidamente le loro variazioni e resi accessibili alle interrogazioni degli utenti, talvolta distribuiti in modo capillare sul territorio. Si pensi, per esempio, all'interrogazione sulla disponibilità di spesa sulle carte di credito, effettuata tramite semplici dispositivi disponibili presso milioni di esercizi commerciali (quali alberghi, negozi o agenzie), che consente di addebitare sulle carte di credito spese effettuate in ogni parte del mondo. Questo libro è dedicato alla gestione dei dati tramite sistemi informatici; descrive perciò i concetti necessari per rappresentare i dati su un calcolatore, i linguaggi che consentono il loro aggiornamento e ritrovamento, e le architetture informatiche specializzate nella gestione dei dati. In questo primo capitolo vengono introdotti i concetti di sistema informativo e di base di dati, per poi soffermarsi sulle principali caratteristiche dei sistemi informatici per gestire basi di dati.

1.1 Sistemi informativi, informazioni e dati N e l l o s v o l g i m e n t o di o g n i attività, sia a livello i n d i v i d u a l e sia in o r g a n i z z a z i o n i di o g n i d i m e n s i o n e , s o n o e s s e n z i a l i la d i s p o n i b i l i t à di i n f o r m a z i o n i e la c a p a c i t à di gestirle in m o d o e f f i c a c e ; o g n i o r g a n i z z a z i o n e è d o t a t a di u n sistema informativo, c h e o r g a n i z z a e g e s t i s c e le i n f o r m a z i o n i n e c e s s a r i e p e r p e r s e g u i r e gli s c o p i d e l l ' o r g a n i z z a z i o n e stessa. L ' e s i s t e n z a del s i s t e m a i n f o r m a t i v o è in p a r t e i n d i p e n d e n t e d a l l a s u a a u t o m a t i z z a z i o n e . A s o s t e g n o di q u e s t a a f f e r m a z i o n e p o s s i a m o r i c o r d a r e c h e i s i s t e m i i n f o r m a t i v i e s i s t o n o d a m o l t o p r i m a d e l l ' i n v e n z i o n e e d e l l a d i f f u s i o n e dei calcolatori elettronici; p e r e s e m p i o , gli archivi delle b a n c h e o dei servizi a n a g r a f i c i s o n o istituiti d a vari secoli. P e r i n d i c a r e la p o r z i o n e a u t o m a t i z z a t a del s i s t e m a inf o r m a t i v o v i e n e di solito u t i l i z z a t o il t e r m i n e sistema informatico. La diffusione capillare d e l l ' i n f o r m a t i c a a q u a s i tutte le attività u m a n e , c h e h a c a r a t t e r i z z a t o gli ultimi v e n t ' a n n i , f a sì c h e g r a n p a r t e dei s i s t e m i i n f o r m a t i v i s i a n o a n c h e , in b u o n a m i s u r a , sistemi i n f o r m a t i c i .

Nelle attività umane più semplici, le informazioni vengono rappresentate e scambiate secondo le tecniche naturali tipiche delle attività stesse: la lingua, scritta o parlata, disegni, figure, numeri. In alcune attività, può addirittura non esistere una rappresentazione esplicita dell'informazione, che viene ricordata a memoria, in maniera più o meno precisa. In ogni caso, possiamo dire che, a mano a mano che le attività si sono andate sistematizzando, sono state individuate opportune forme di organizzazione e codifica delle informazioni. Nei sistemi informatici, per ragioni che in parte sono tecnologiche e in parte sono legate alla semplicità dei meccanismi di gestione, il concetto di rappresentazione e codifica viene portato all'estremo: le informazioni vengono rappresentate per mezzo di dati, che hanno bisogno di essere interpretati per fornire informazioni. Come per molti termini fondamentali, è difficile dare una definizione precisa del concetto di dato e soprattutto delle differenze fra dato e informazione: in modo approssimativo possiamo dire che i dati da soli non hanno alcun significato, ma, una volta interpretati e correlati opportunamente, essi forniscono informazioni, che consentono di arricchire la nostra conoscenza del mondo. Come ulteriore contributo riportiamo le definizioni dei due termini contenute in un recente dizionario [69]: informazione: notizia, dato o elemento che consente di avere conoscenza più o meno esatta di fatti, situazioni, modi di essere; dato: ciò che è immediatamente presente alla conoscenza, prima di ogni elaborazione; (in informatica) elementi di informazione costituiti da simboli che devono essere elaborati. Per esempio, la stringa F e r r a r i e il numero 8, scritti su un foglio di carta, sono due dati e da soli non significano niente. Se il foglio di carta è relativo alle ordinazioni presso il ristorante di un albergo la notte di Capodanno e sono note le regole che camerieri e cassiere devono seguire, allora si può dedurre che è stata ordinata una bottiglia di spumante della marca 'Ferrari', che va addebitata sul conto della camera numero 8: con le indicazioni aggiuntive, i dati diventano informazione e arricchiscono la conoscenza. Chiaramente, un foglietto con gli stessi dati sul taccuino di un radiocronista sportivo avrebbe un significato molto diverso. Introdotto così il concetto di dato, possiamo passare a quello di base di dati, oggetto principale di questo testo. Varie accezioni sono possibili per questo termine; secondo la più generale di esse, una base di dati è una collezione di dati, utilizzati per rappresentare le informazioni di interesse per un sistema informativo. In questo libro, considereremo una accezione molto più specifica del termine. A tale scopo è dedicato il Paragrafo 1.2. Concludiamo invece questo paragrafo con una osservazione. In molte applicazioni, i dati hanno caratteristiche più stabili rispetto a quelle delle procedure (manuali o automatizzate) che operano su di essi. Riferendoci a un esempio già citato, possiamo osservare che i dati relativi alle applicazioni bancarie hanno una struttura sostanzialmente invariata da decenni, mentre le procedure che agiscono su di essi variano con una certa frequenza, come ogni cliente può facilmente verificare. Tra l'altro, quando una procedura sostituisce un'altra, la nuova procedura

"eredita" i dati della vecchia, con opportune trasformazioni, più o meno semplici. Questa caratteristica di stabilità porta ad affermare che i dati costituiscono una "risorsa" per l'organizzazione che li gestisce, un patrimonio significativo da sfruttare e proteggere.

1.2 Basi di dati e sistemi di gestione di basi di dati L'attenzione ai dati ha caratterizzato le applicazioni dell'infonnatica fin dalle sue origini, ma sistemi software specificamente dedicati alla gestione dei dati sono stati realizzati solo a partire dalla fine degli anni Sessanta del secolo scorso, e tuttora alcune applicazioni non ne fanno uso. In assenza di un software specifico, la gestione dei dati è affidata ai linguaggi di programmazione tradizionali, per esempio C e Fortran, oppure, in tempi più recenti, ai linguaggi a oggetti, tra cui C++ e Java. Esistono ancora diverse applicazioni scritte in COBOL, un linguaggio di programmazione degli anni Sessanta, che può ritenersi ormai superato. L'approccio "convenzionale" alla gestione dei dati sfrutta la presenza di archivi o file per memorizzare i dati in modo persistente sulla memoria di massa. Un file consente di memorizzare e ricercare dati, ma fornisce solo semplici meccanismi di accesso e di condivisione. Secondo questo approccio, le procedure scritte in un linguaggio di programmazione sono completamente autonome; ciascuna di esse definisce e utilizza uno o più file "privati". Eventuali dati di interesse per più programmi sono replicati tante volte quanti sono i programmi che li utilizzano, con evidente ridondanza e possibilità di incoerenza. Illustriamo questo concetto con riferimento a una situazione reale, di media complessità. In un'università, le informazioni relative ai docenti possono essere utilizzate in vario modo e da diverse persone o uffici; per esempio, potremmo avere le seguenti situazioni (alcune delle quali sono state semplificate o adattate a fini di presentazione): • l'ufficio del personale è di solito responsabile delle informazioni relative alla "carriera" (per esempio, alla distinzione fra ricercatore, professore associato e professore ordinario e alla anzianità); • le presidenze delle facoltà (sulla base delle delibere dei consigli delle facoltà stesse) mantengono le informazioni sugli incarichi di insegnamento dei docenti; • l'ufficio Web di Ateneo, interessato a pubblicare le informazioni sui corsi e i relativi docenti, utilizza parte di quelle illustrate ai punti precedenti, ma necessita anche di altre, per esempio i recapiti dei docenti e i programmi dei corsi; • l'ufficio stipendi (quasi sempre diverso dall'ufficio del personale) utilizza le informazioni sulla carriera e quelle sugli incarichi didattici per calcolare le retribuzioni, sulla base delle regole fissate dalla legge e delle eventuali integrazioni locali. Se ciascuno di questi soggetti gestisse separatamente le informazioni di proprio interesse, avremmo molte duplicazioni e, come spesso succede in presenza di duplicazioni, a lungo andare ci sarebbero molti dati con le varie copie non aggiorna-

te nello stesso modo. Per esempio, potremmo trovare sul sito Web una qualifica diversa da quella corretta, riportata nell'archivio dell'ufficio del personale. Le basi di dati sono state concepite in buona misura per superare questo tipo di inconvenienti, gestendo in modo integrato e flessibile le informazioni di interesse per diversi soggetti, limitando i rischi di ridondanza e incoerenza. In generale, potremmo dire che una base di dati è semplicemente una collezione di dati, di interesse per una qualche applicazione. Preferiamo però dare una definizione che abbia un contenuto anche tecnologico. Un sistema di gestione di basi di dati (in inglese Data Base Management System, abbreviato con DBMS) è un sistema software in grado di gestire collezioni di dati che siano grandi, condivise e persistenti, assicurando la loro affidabilità e privatezza. Come ogni prodotto informatico, un DBMS deve essere efficiente ed efficace. Una base di dati è una collezione di dati gestita da un DBMS. Precisiamo le caratteristiche dei DBMS e delle basi di dati su cui si fondano le definizioni date in precedenza. • Le basi di dati sono grandi, nel senso che possono avere anche dimensioni enormi e comunque in generale molto maggiori della memoria centrale disponibile. Alla data di redazione di questo testo, le più grandi basi di dati hanno dimensioni dell'ordine delle centinaia (o forse migliaia) di terabyte e contengono migliaia di miliardi di record. Di conseguenza, i DBMS devono prevedere una gestione dei dati in memoria secondaria. Ovviamente, possono esistere anche basi di dati "piccole", ma i sistemi devono poter gestire i dati senza porre limiti alle dimensioni, a parte quelle fisiche dei dispositivi. • Le basi di dati sono condivise, nel senso che applicazioni e utenti diversi devono poter accedere, secondo opportune modalità, a dati comuni. È importante notare che in questo modo si riduce la ridondanza dei dati, poiché si evitano ripetizioni, e conseguentemente si riduce anche la possibilità di inconsistenze: se esistono varie copie degli stessi dati, è possibile che esse, in qualche momento, non siano uguali; viceversa, se ogni dato è memorizzato sul calcolatore in modo univoco, non è possibile incorrere in disallineamenti. Per garantire l'accesso condiviso ai dati da parte di molti utenti che operano contemporaneamente, il DBMS dispone di un meccanismo apposito, detto controllo di concorrenza. Esistono al giorno d'oggi basi di dati che devono gestire più di dieci milioni di operazioni (per esempio, lettura o scrittura di record) al secondo. • Le basi di dati sono persistenti, cioè hanno un tempo di vita che non è limitato a quello delle singole esecuzioni dei programmi che le utilizzano. In contrasto, ricordiamo che i dati gestiti da un programma in memoria centrale hanno una vita che inizia e termina con l'esecuzione del programma; tali dati, quindi, non sono persistenti. • I DBMS garantiscono la affidabilità, cioè la capacità del sistema di conservare sostanzialmente intatto il contenuto della base di dati (o almeno di permetterne la ricostruzione) in caso di malfunzionamenti hardware e software. Questo aspetto è essenziale se si pensa che in molte applicazioni (per esempio quelle finanziarie) ogni dato ha un valore enorme, che deve essere preservato nel tempo e a fronte di qualsiasi guasto del sistema, errore umano, o anche evento

catastrofico. A questo scopo i DBMS forniscono specifiche funzionalità di salvataggio e ripristino (backup e recovery). In alcuni casi, i DBMS gestiscono, in modo controllato, versioni replicate dei dati, collocate su dispositivi fisici diversi e talvolta su server che sono disposti a distanza, così da garantire maggiore affidabilità complessiva. • I DBMS garantiscono la privatezza dei dati. Ciascun utente, riconosciuto in base a un nome d'utente che è specificato all'atto di interagire con il DBMS, viene abilitato a svolgere solo determinate azioni sui dati, attraverso meccanismi di autorizzazione. • I DBMS sono efficienti, cioè capaci di svolgere le operazioni utilizzando un insieme di risorse (tempo e spazio) che sia accettabile per gli utenti. Questa caratteristica dipende dalle tecniche utilizzate nell'implementazione del DBMS e dalla bontà della realizzazione della base di dati da parte dei suoi progettisti. Va sottolineato che i DBMS forniscono un insieme piuttosto ampio di funzionalità che richiedono molte risorse, e quindi possono garantire efficienza solo a condizione che il sistema informatico su cui sono installati sia adeguatamente dimensionato. • I DBMS sono efficaci in quanto sono capaci di rendere produttive, in ogni senso, le attività dei loro utenti. Questa definizione è chiaramente generica e non corrisponde a un aspetto specifico. L'attività di progettazione della base di dati e delle applicazioni che la utilizzano mira essenzialmente a garantire una buona efficacia complessiva del sistema. È importante sottolineare che la gestione di collezioni di dati grandi e persistenti è possibile anche per mezzo di strumenti meno sofisticati dei DBMS, a cominciare dai file già citati, presenti in tutti i sistemi operativi. I file sono stati introdotti per gestire insiemi di dati "localmente" a una specifica procedura o applicazione. I DBMS sono stati concepiti e realizzati per estendere le funzioni dei file system, fornendo la possibilità di accesso condiviso agli stessi dati da parte di più utenti e applicazioni, e garantendo anche molti altri servizi in maniera integrata. Precisiamo inoltre che i DBMS, a loro volta, utilizzano file per la memorizzazione dei dati; i file gestiti dal DBMS ammettono però organizzazioni dei dati più sofisticate. Ritornando all'esempio brevemente illustrato all'inizio di questo paragrafo, possiamo dire che un modello ideale che adotti fino in fondo le idee appena discusse dovrebbe prevedere l'utilizzo di una sola base di dati, con tutte le informazioni di interesse (e quindi non solo quelle sui docenti, ma per esempio anche quelle sui corsi e sulle varie strutture dell'ateneo, e cioè facoltà, dipartimenti e corsi di laurea, nonché sugli aspetti contabili e amministrativi e tanti altri che non abbiamo per niente citato). Tale base di dati verrebbe poi a essere utilizzata dai vari uffici (e persone), ciascuno per le proprie competenze, attraverso programmi diversi. In effetti, in molti casi, non è possibile o non è conveniente, per varie ragioni, avere un'unica base di dati, ma è importante avere presente che l'obiettivo della integrazione e condivisione è comunque importante, e che i flussi di informazione devono essere coordinati e governati: nell'esempio, l'utilizzo della stessa base di dati da parte dell'ufficio stipendi e dell'ufficio del personale è senz'altro un obiettivo importante. Viceversa, può essere più difficile integrare i dati di questa

base di dati con quelli del sito Web, in quanto quest'ultimo deve essere sempre disponibile per la consultazione, oltre che accessibile dall'esterno, mentre buona parte dei dati sul personale, non rilevanti per il sito, sono riservati e delicati. È quindi ragionevole pensare a soluzioni che prevedano l'uso di una base di dati per mantenere i dati di interesse per il sito Web, diversa da quella relativa a personale e stipendi. È però opportuno pensare che la base di dati per il sito Web sia periodicamente aggiornata, in modo predefinito e automatico, con le informazioni sulle carriere dei docenti, al fine di evitare incoerenze. Più in generale, possiamo pensare che una organizzazione complessa (azienda o ente pubblico) utilizzi un insieme di basi dati, che siano ciascuna dedicata a un insieme di applicazioni strettamente correlate (quindi con un certo grado di integrazione e condivisione) e che siano al tempo stesso coinvolte in operazioni di interscambio di informazioni finalizzate a evitare duplicazioni di dati e ripetizioni di attività. Abbiamo detto che un DBMS mette a disposizione una base di dati in generale a più utenti e ai loro programmi. Torneremo presto, nel Paragrafo 1.4, a commentare le caratteristiche dei programmi (e linguaggi utilizzati per scriverli) e degli utenti. Qui invece facciamo un'altra osservazione, relativa peraltro a un argomento che non viene sviluppato in questo volume, ma nel secondo [5]. Esistono varie organizzazioni architetturali per l'accesso a basi di dati: per esempio, i programmi possono essere eseguiti sullo stesso calcolatore che gestisce i dati oppure su un altro; gli utenti possono utilizzare i cosiddetti "terminali stupidi", cioè privi di capacità elaborativa, oppure personal computer che svolgono parte delle attività, in una architettura di tipo "client/server". Negli ultimi anni, si è poi molto diffuso l'accesso a basi di dati attraverso il World Wide Web: in effetti, la maggior parte dei siti Web contengono pagine che sono generate dinamicamente (cioè al momento della richiesta) a partire da dati contenuti in basi di dati.

1.3 Modelli dei dati Un modello dei dati è un insieme di concetti utilizzati per organizzare i dati di interesse e descriverne la struttura in modo che essa risulti comprensibile a un elaboratore. Ogni modello dei dati fornisce meccanismi di strutturazione, analoghi ai costruttori di tipo dei linguaggi di programmazione, che permettono di definire nuovi tipi sulla base di tipi predefiniti (elementari) e costruttori di tipo. Per esempio, il C permette di costruire tipi per mezzo dei costruttori struct, union, enum, * (pointer). Il modello relazionale dei dati, attualmente il più diffuso, permette di definire tipi per mezzo del costruttore relazione, che consente di organizzare i dati in insiemi di record a struttura fissa. Una relazione viene spesso rappresentata per mezzo di una tabella, le cui righe rappresentano specifici record e le cui colonne corrispondono ai campi del record; l'ordine delle righe e delle colonne è sostanzialmente irrilevante. Per esempio, i dati relativi ai corsi universitari e ai loro docenti e all'inserimento dei corsi nel manifesto degli studi dei vari corsi di laurea possono essere organizzati per mezzo di due relazioni, DOCENZA e MA-

DOCENZA Corso

NomeDocente

Basi di dati Reti Linguaggi

Rossi Neri Verdi

CdL

Materia

Anno

Inglnf Inglnf Inglnf IngEl IngEl

Basi di dati Reti Linguaggi Basi di dati Reti

2 3 2 3 3

Figura 1.1 Esempio di base di dati relazionale

NIFESTO, rappresentabili con le tabelle in Figura 1.1. Come si vede nella figura, in una base di dati relazionale ci sono in generale più relazioni. Il modello relazionale, definito formalmente agli inizi degli anni Settanta del secolo scorso, ma affermatosi nel decennio successivo, è, come abbiamo detto, il più diffuso e viene utilizzato in questo libro come modello di riferimento. Oltre al modello relazionale sono stati definiti altri quattro tipi di modelli: • il modello gerarchico, basato sull'uso di strutture ad albero (e quindi gerarchie, da cui il nome), definito durante la prima fase di sviluppo dei DBMS (anni Sessanta), ma tuttora ampiamente utilizzato; • il modello reticolare (detto anche modello CODASYL, dal comitato di standardizzazione che lo definì con precisione), basato sull'uso di grafi, sviluppato successivamente al modello gerarchico (inizio anni Settanta); • il modello a oggetti, sviluppato negli anni Ottanta come evoluzione del modello relazionale, che estende alle basi di dati il paradigma di programmazione a oggetti; al modello a oggetti è dedicato un capitolo nel secondo volume [5]; • il modello XML, sviluppato negli anni Novanta come rivisitazione del modello gerarchico, in cui però i dati vengono presentati assieme alla loro descrizione e non devono sottostare rigidamente a un'unica struttura logica (tenuto conto di queste due caratteristiche, si dice che il modello XML è auto-descrittivo e semi-strutturato); anche questo modello è approfondito nel secondo volume [5]. I modelli dei dati precedentemente elencati sono effettivamente disponibili su DBMS commerciali; essi vengono detti logici, per sottolineare il fatto che le strutture utilizzate da questi modelli, pur essendo astratte, riflettono una particolare organizzazione (ad alberi, a grafi, a tabelle o a oggetti). Più recentemente, sono stati introdotti altri modelli dei dati, detti concettuali, utilizzati per descrivere i dati in maniera completamente indipendente dalla scelta del modello logico. Questi modelli non sono disponibili su DBMS commerciali. Il loro nome deriva dal fatto che essi tendono a descrivere i concetti del mondo reale, piuttosto che i dati utili a rappresentarli. Essi vengono utilizzati nella fase preliminare del processo di progettazione di basi di dati, per analizzare nel modo migliore la realtà di interesse, senza "contaminazioni" di tipo realizzativo. Nella Parte Seconda di que-

sto libro, dedicata al progetto delle basi di dati, vedremo in dettaglio un modello concettuale, il modello Entità-Relazione.

1.3.1 Schemi e istanze Nelle basi di dati esiste una parte sostanzialmente invariante nel tempo, detta schema della base di dati, costituita dalle caratteristiche dei dati, e una parte variabile nel tempo, detta istanza o stato della base di dati, costituita dai valori effettivi. Nell'esempio della Figura 1.1, le relazioni hanno una struttura fissa: la relazione DOCENZA ha due colonne (dette attributi), che si riferiscono rispettivamente a corsi e docenti. Lo schema di una relazione è costituito dalla sua intestazione, cioè dal nome della relazione seguito dai nomi dei suoi attributi; per esempio: DocENZA(Corso,NomeDocente) Viceversa, le righe della tabella variano nel tempo, e corrispondono ai corsi attualmente offerti e ai relativi docenti. Durante la vita della base di dati, docenti e corsi vengono aggiunti, tolti o modificati; in modo analogo, il manifesto degli studi viene modificato di anno in anno. L'istanza di una relazione è costituita dall'insieme, variante nel tempo, delle sue righe; nell'esempio abbiamo le tre coppie: Basi di dati Reti Linguaggi

Rossi Neri Verdi

Si dice anche che lo schema è la componente intensionale della base di dati e l'istanza la componente estensionale. Queste definizioni verranno riprese e sviluppate ulteriormente nel Capitolo 2.

1.3.2 Livelli di astrazione nei DBMS La nozione di modello e di schema descritta in precedenza può essere ulteriormente sviluppata tenendo presenti altre dimensioni nella descrizione dei dati. In particolare, esiste una proposta di architettura standardizzata per D B M S articolata su tre livelli, detti rispettivamente esterno, logico1 e interno-, per ciascun livello esiste uno schema. • Lo schema logico costituisce una descrizione dell'intera base di dati per mezzo del modello logico adottato dal D B M S (cioè tramite uno dei modelli descritti in precedenza: relazionale, gerarchico, reticolare o a oggetti).

1

Questo livello viene da alcuni autori chiamato concettuale, seguendo la terminologia utilizzata originariamente nella proposta. Noi preferiamo il termine "logico", in quanto, come abbiamo visto, usiamo il termine "concettuale" per altri scopi.

• Lo schema interno costituisce la rappresentazione dello schema logico per mezzo di strutture fisiche di memorizzazione. Per esempio, una relazione può essere realizzata fisicamente per mezzo di un file sequenziale, o di un file hash, o di un file sequenziale con uno o più indici. • Uno schema esterno costituisce la descrizione di una porzione della base di dati di interesse, per mezzo del modello logico. Uno schema esterno può prevedere organizzazioni dei dati diverse rispetto a quelle utilizzate nello schema logico, che riflettono il punto di vista di un particolare utente o insieme di utenti. Pertanto, è possibile associare a uno schema logico vari schemi esterni. Nei sistemi più moderni il livello esterno non è esplicitamente presente, ma è possibile definire relazioni derivate (o viste, dall'inglese views). Per esempio, relativamente alla base di dati di Figura 1.1, uno studente del corso di laurea in Ingegneria Elettronica (IngEl) potrebbe essere interessato solo ai corsi offerti dal manifesto del suo corso di laurea; questa informazione è presente nella relazione ELETTRONICA, mostrata in Figura 1.2, ottenuta come vista a partire dalla relazione MANIFESTO. Inoltre, tramite il meccanismo delle autorizzazioni di accesso, è possibile disciplinare gli accessi degli utenti alla base di dati.

1.3.3 Indipendenza dei dati L'architettura a livelli così definita garantisce l'indipendenza dei dati, la principale proprietà dei DBMS. In generale, questa proprietà permette a utenti e programmi applicativi che utilizzano una base di dati di interagire a un elevato livello di astrazione, che prescinde dai dettagli realizzativi utilizzati nella costruzione della base di dati. In particolare, l'indipendenza dei dati può essere caratterizzata ulteriormente come indipendenza fisica e logica. • L'indipendenza fisica consente di interagire con il DBMS in modo indipendente dalla struttura fisica dei dati. In base a questa proprietà è possibile modificare le strutture fisiche (per esempio le modalità di organizzazione dei file gestiti dal DBMS o la allocazione fisica dei file sui dispositivi di memorizzazione) senza influire sulle descrizioni dei dati ad alto livello e quindi sui programmi che utilizzano i dati stessi. • L'indipendenza logica consente di interagire con il livello esterno della base di dati in modo indipendente dal livello logico. Per esempio, è possibile aggiungere uno schema esterno in base alle esigenze di un nuovo utente oppure modificare uno schema esterno senza dover modificare lo schema logico e perciò

la sottostante organizzazione fìsica dei dati. Dualmente, è possibile modificare il livello logico, mantenendo inalterate le strutture esterne (modificandone ovviamente la definizione in termini delle strutture logiche) di interesse per l'utente. È importante sottolineare che gli accessi alla base di dati avvengono solo attraverso il livello esterno (che può coincidere con quello logico); è il DBMS che traduce le operazioni in termini dei livelli sottostanti. L'architettura a livelli è quindi il meccanismo fondamentale attraverso cui i DBMS realizzano l'indipendenza dei dati.

1.4 Linguaggi e utenti delle basi di dati I DBMS sono caratterizzati, da un lato, dalla presenza di molteplici linguaggi per la gestione dei dati; dall'altro, dalla presenza di molteplici tipologie di utenti.

1.4.1 Linguaggi per basi di dati Su un DBMS è possibile specificare operazioni di vario tipo, in particolare quelle relative agli schemi e alle istanze. Al riguardo, i linguaggi per basi di dati si distinguono in due categorie: • linguaggi di definizione dei dati o Data Definition Language (abbreviato con DDL), utilizzati per definire gli schemi logici, esterni e fisici e le autorizzazioni per l'accesso; • linguaggi di manipolazione dei dati o Data Manipulation Language (abbreviato con DML), utilizzati per l'interrogazione e l'aggiornamento delle istanze di basi di dati. Va sottolineato che alcuni linguaggi, come per esempio il linguaggio SQL, che vedremo approfonditamente nei Capitoli 4 e 5, presentano in forma integrata le funzionalità di entrambe le categorie. L'accesso ai dati può essere effettuato con varie modalità: • tramite linguaggi testuali ipterattivi, soprattutto il linguaggio SQL, nelle sue varie versioni; per esempio, possiamo definire la struttura della relazione DOCENZA, già mostrata in Figura 1.1, sottoponendo a un interprete SQL (disponibile in tutti i DBMS) la seguente istruzione 2 (che appartiene quindi al DDL): create table Corso NomeDocente

)

Docenza( character(20), character(30)

"Per non appesantire, mostriamo una istruzione che, pur formalmente corretta, è incompleta, in quanto, come vedremo più avanti, non contiene la specifica della chiave primaria.

La seguente istruzione, invece, permette di visualizzare, sempre in un ambiente interattivo, i corsi di ingegneria informatica del secondo anno con i relativi docenti: select Corso, NomeDocente from Docenza, Manifesto where Corso=Materia and Anno=2 and CdL='Inglnf' • tramite comandi simili a quelli interattivi immersi in linguaggi di programmazione, quali C, C++, Java, COBOL, come vedremo nel Capitolo 6. Questi linguaggi di programmazione si dicono linguaggi ospite perché "ospitano" comandi scritti nel linguaggio per basi di dati. Una caratteristica importante di questo approccio è la possibilità di realizzare applicazioni parametriche e di farle eseguire anche a un utente che non conosca SQL: con riferimento al semplice esempio precedente, si potrà scrivere un programma che permette di ricercare corsi e docenti per un certo corso di laurea e un certo anno, specificati dall'utente solo al momento dell'esecuzione del programma (ma non noti al momento della scrittura dello stesso); • tramite comandi simili a quelli interattivi immersi in linguaggi di sviluppo ad hoc, spesso con funzionalità specifiche (per esempio per la generazione di grafici, di stampe complesse, oppure di maschere su video). Questi linguaggi variano purtroppo molto da sistema a sistema e potremo quindi solo accennare ad alcuni aspetti nelle appendici, che sono appunto dedicate a specifici sistemi; • tramite interfacce amichevoli che permettono di sintetizzare interrogazioni senza usare un linguaggio testuale. Anche queste interfacce differiscono molto le une dalle altre e sono in continua evoluzione. Pure per esse, accenneremo nelle appendici agli aspetti più semplici e importanti. Vediamo per ora un esempio, relativo alla stessa interrogazione vista sopra in SQL: la Figura 1.3 mostra la sua realizzazione in Access, il sistema più diffuso per la gestione di basi di dati in ambiente individuale. Una gran parte dei programmi per la immissione dei dati, la loro gestione e la stampa hanno una struttura regolare; conseguentemente, la presenza di linguaggi di sviluppo e di interfacce amichevoli può semplificare significativamente la produzione di applicazioni, facilitando il compito del programmatore e riducendo i tempi e i costi di sviluppo.

1.4.2 Utenti e progettisti Varie categorie di persone possono interagire con una base di dati o con un DBMS. Descriviamo brevemente le più importanti. • L'amministratore della base di dati (o Database Administrator, abbreviato con DBA) è la persona (o gruppo di persone) responsabile della progettazione, controllo e amministrazione della base di dati. Il DBA ha il compito di mediare le

^

Esempio Docenza

Manifesto

Corso NomeDoeente

[I

CdL Materia Anno

^—

< u Campo:

Corso

NomeDoeente

CdL

Anno

Tabella:

Docenza

Docenza

Manifesto

Manifesto

Ordinamento: Mostra :

0

0

Criteri:

"Inglnf"



2



Oppure:



i B

»

5

0

Corso

o

I -

B a s i di dati

£«

a M

Esempio H

| Linguaggi

Record: 14

Pronto



M

S

M

NomeDoeente

I

M

I

I

!

^

^

X

-

Rossi Verdi

1 di 2

• M

«

; Cerca

Jig à ® sm

Figura 1.3 Un'interrogazione formulata in Access e il suo risultato

varie esigenze espresse dagli utenti, in genere contrastanti fra loro, garantendo un controllo centralizzato sui dati. L'amministratore delle basi di dati è responsabile, in particolare, di garantire sufficienti prestazioni, di assicurare l'affidabilità del sistema, e di gestire le autorizzazioni di accesso ai dati. Al progetto delle basi di dati è dedicata la Parte Seconda del libro. I progettisti e programmatori di applicazioni definiscono e realizzano i programmi che accedono alla base di dati. Essi utilizzano il linguaggio di manipolazione dei dati (DML) oppure i vari strumenti di supporto alla generazione di interfacce verso la base di dati descritti in precedenza. Alla programmazione di applicazioni sulle basi di dati sono dedicati i capitoli relativi al linguaggio SQL, nella Parte Prima del testo. Gli utenti utilizzano la base di dati per le proprie attività. Essi possono a loro volta essere divisi in due categorie: - utenti finali (o terminalisti), che utilizzano transazioni, cioè programmi che realizzano attività predefinite e di frequenza elevata, con poche eccezioni previste a priori; - utenti casuali, in grado di impiegare i linguaggi interattivi per l'accesso alla

base di dati, formulando interrogazioni (o aggiornamenti) di tipo vario. Essi possono essere specializzati (rispetto al linguaggio che utilizzano) e interagire frequentemente con la base di dati. Si noti che il termine "casuale" sta a indicare il fatto che le interrogazioni specificate da utenti casuali non sono predefinite.

1.5 Vantaggi e svantaggi dei DBMS Concludiamo questo capitolo riassumendo le caratteristiche essenziali delle basi di dati e dei DBMS, e i relativi vantaggi e svantaggi. Possiamo elencare i seguenti vantaggi. • I DBMS permettono di considerare i dati come una risorsa comune di una organizzazione, a disposizione (con opportune forme di controllo) di tutte le sue componenti. • La base di dati fornisce un modello unificato e preciso della parte del mondo reale di interesse per l'organizzazione, utilizzabile nelle applicazioni attuali e, con possibili estensioni, in applicazioni future. • Con l'uso di un DBMS è possibile un controllo centralizzato dei dati, che può essere arricchito da forme di standardizzazione e beneficiare di "economie di scala". • La condivisione permette di ridurre ridondanze e inconsistenze. • L'indipendenza dei dati, caratteristica fondamentale dei DBMS, favorisce lo sviluppo di applicazioni più flessibili e facilmente modificabili. L'uso dei DBMS comporta anche alcuni aspetti negativi, o almeno delicati, fra i quali i seguenti. • I DBMS sono prodotti costosi, complessi e abbastanza diversi da molti altri strumenti informatici. La loro introduzione comporta quindi notevoli investimenti, diretti (acquisto del prodotto) e indiretti (acquisizione delle risorse hardware e software necessarie, conversione delle applicazioni, formazione del personale). • I DBMS forniscono, in forma integrata, una serie di servizi, che sono necessariamente associati a un costo. Nei casi in cui alcuni di questi servizi non siano necessari, è difficile scorporare quelli effettivamente richiesti dagli altri, e ciò può comportare una riduzione di prestazioni. Concludendo, possiamo dire che si incontrano situazioni nelle quali l'adozione di un DBMS può risultare sconveniente: applicazioni con uno o pochi utenti, senza necessità di accessi concorrenti e relativamente stabili nel tempo possono essere realizzate più proficuamente con file ordinari piuttosto che con DBMS. Tuttavia, la tecnologia dei DBMS si è notevolmente evoluta negli ultimi anni, traducendosi in sistemi sempre più efficienti e affidabili su architetture sempre più diffuse e poco costose, aumentando la convenienza di sviluppare applicazioni con un DBMS.

Note bibliografiche Esistono molti testi di tipo generale sulle basi di dati, quasi tutti in lingua inglese ma poi tradotti in italiano: segnaliamo in particolare quelli di ElMasri e Navathe [32], Silberschatz, Korth e Sudarshan [59], Ramakhrishnan e Gehrke [54] e Garcia-Molina, Ullman e Widom [36], che coprono in modo equilibrato gli aspetti metodologici e quelli tecnologici. Il testo di Date [29], molto diffuso e ormai alla ottava edizione, presenta in modo semplice molti aspetti importanti. Quello di Ullman [67] tratta in modo integrato tecnologia esistente e aspetti di natura teorica. Per dettagli relativi ai singoli aspetti citati in questo capitolo, rimandiamo ai capitoli successivi, in cui verranno approfonditi, e alle relative note bibliografiche.

Parte prim; Basi di dati relazionali: modello e linguaggi

Il modello relazionale

La maggior parte dei sistemi di basi di dati oggi sul mercato si fonda sul modello relazionale, che fu proposto in una pubblicazione scientifica (di E.F. Codd [24]), nel 1970, al fine di superare le limitazioni dei modelli all'epoca utilizzati a livello logico, che non permettevano di realizzare efficacemente la proprietà di indipendenza dei dati, già riconosciuta fondamentale. L'affermazione del modello relazionale è stata abbastanza lenta, a causa proprio dell'alto livello di astrazione: non è stato immediato individuare realizzazioni efficienti per strutture significativamente diverse da quelle utilizzate allora. Infatti, nonostante i primi prototipi di sistemi relazionali siano stati realizzati già nei primi anni Settanta, i primi sistemi relazionali sono apparsi sul mercato nel 1981, acquisendone una frazione significativa solo a metà degli anni Ottanta. La presentazione del modello relazionale è articolata in cinque capitoli, questo e i quattro successivi. Nel presente capitolo sono illustrate le caratteristiche strutturali del modello, cioè le modalità secondo cui esso permette di organizzare i dati. Dopo una breve discussione sui vari modelli logici, si mostra come il concetto di relazione possa essere mutuato dalla teoria degli insiemi e utilizzato, con alcune varianti, per rappresentare le informazioni di interesse in una base di dati. Viene in particolare approfondito il fatto che le corrispondenze fra dati in strutture diverse sono rappresentate per mezzo dei dati stessi. Poi, dopo una breve discussione delle modalità per la rappresentazione di informazione incompleta, l'attenzione viene volta ai vincoli di integrità, che permettono di specificare proprietà aggiuntive che devono essere soddisfatte dalle basi di dati. La presentazione del modello relazionale è completata nei quattro capitoli successivi, il primo dedicato alla specifica delle operazioni di interrogazione di basi di dati relazionali e gli altri al linguaggio SQL, che, nei DBMS oggi esistenti, permette di definire, aggiornare e interrogare basi di dati.

2.1 II modello relazionale: strutture 2.1.1 Modelli logia nei sistemi di basi di dati Il modello relazionale si b a s a su d u e concetti, relazione e tabella, di n a t u r a d i v e r s a m a f a c i l m e n t e riconducibili l ' u n o a l l ' a l t r o . L a n o z i o n e di relazione p r o v i e n e d a l l a m a t e m a t i c a , in p a r t i c o l a r e d a l l a teoria degli i n s i e m i , m e n t r e il c o n c e t t o di tabella è s e m p l i c e e intuitivo. L a p r e s e n z a c o n t e m p o r a n e a di q u e s t i d u e concetti, l ' u n o f o r m a l e e l ' a l t r o intuitivo, è r e s p o n s a b i l e del g r a n d e s u c c e s s o o t t e n u t o dal m o d e l l o r e l a z i o n a l e . Infatti, le tabelle r i s u l t a n o naturali e c o m p r e n s i b i l i a n c h e per gli utenti

finali (che spesso le utilizzano in tanti contesti per scopi diversi, senza riferimento alle basi di dati). D'altra parte, la disponibilità di una formalizzazione semplice e precisa ha permesso anche uno sviluppo teorico a supporto del modello con risultati di interesse concreto. Il modello relazionale risponde al requisito dell'indipendenza dei dati, che, come abbiamo visto nel Capitolo 1, prevede una distinzione, nella descrizione dei dati, fra il livello fisico e il livello logico-, gli utenti che accedono ai dati e i programmatori che sviluppano le applicazioni fanno riferimento solo al livello logico; i dati descritti al livello logico sono poi realizzati per mezzo di opportune strutture fisiche, ma per accedere ai dati non è necessario conoscere le strutture fisiche stesse. Al contrario, i modelli proposti precedentemente al modello relazionale, quello reticolare e quello gerarchico, includevano espliciti riferimenti alla sottostante struttura realizzativa, attraverso l'uso di puntatori e l'ordinamento fisico dei dati. Una precisazione è utile prima di passare all'introduzione del modello relazionale. Il termine relazione viene utilizzato in questo testo (e in generale con riferimento alle basi di dati) in tre accezioni che, nei dettagli, differiscono in modo importante: • relazione matematica, secondo la definizione normalmente data nella teoria degli insiemi elementare. Da questa nozione, che verrà richiamata nel prossimo paragrafo, derivano le altre due; • relazione secondo la definizione del modello relazionale che, come vedremo nel Paragrafo 2.1.3, presenta alcune differenze rispetto a quella della teoria degli insiemi; • relazione, come traduzione di relationship,1 costrutto del modello concettuale Entità-Relazione (in inglese Entity-Relationship) utilizzato, come vedremo nel Capitolo 7, per descrivere legami tra entità del mondo reale.

2.1.2 Relazioni e tabelle Ricordiamo che, in matematica, dati due insiemi Di e D2, si chiama prodotto cartesiano di D\ e D2, in simboli D\ x D2, l'insieme delle coppie ordinate (ui, v2), tali che t>i è un elemento di D\ e v2 è un elemento di D2. Per esempio, dati gli insiemi A = {1, 2, 4} e fi = {a, b), il prodotto cartesiano A x fi è costituito dall'insieme di tutte le possibili coppie in cui il primo elemento appartiene ad A e il secondo a fi. Poiché A ha tre elementi e fi due, si tratta quindi di sei coppie: {{\,a),(\,b),{2,a),{2,

b), (4,a),

(4, b)}

'Nei due casi precedenti si usa in inglese il termine relation, che quindi non è ambiguo rispetto a relationship. Talvolta sono usate altre traduzioni per relationship, come associazione o correlazione.

Una relazione matematica sugli insiemi D\ e D2 (chiamati domini della relazione) è un sottoinsieme di D\ x D 2 . Dati gli insiemi A e fi di cui sopra, una possibile relazione matematica su A e fi è costituita dall'insieme di coppie {(l,a),(l»,(4,è)}. Le relazioni possono essere rappresentate graficamente, in maniera utilmente espressiva, sotto forma tabellare. Le due tabelle riportate nella Figura 2.1 descrivono il prodotto cartesiano A x fi e la relazione matematica su A e fi sopra discusse. Vale la pena fare una annotazione, importante dal punto di vista formale (anche se pressoché ovvia da quello pratico). Finora non abbiamo detto niente riguardo alla finitezza degli insiemi che consideriamo, e abbiamo quindi implicitamente ammesso la possibilità di insiemi infiniti (e perciò di relazioni infinite). In pratica, poiché le nostre basi di dati devono essere memorizzate in sistemi di calcolo di dimensione finita, le relazioni sono necessariamente finite. Peraltro, in talune trattazioni teoriche, che comunque esulano dagli interessi di questo testo, vengono talvolta ammesse relazioni infinite. Al tempo stesso, è comodo a volte che i domini abbiano dimensione infinita (in modo che sia sempre possibile assumere l'esistenza di un valore non presente nella base di dati). Pertanto, assumeremo ove necessario che le nostre basi di dati siano costituite da relazioni finite su domini eventualmente infiniti. Le definizioni precedenti di prodotto cartesiano e relazione matematica fanno riferimento a due insiemi, ma possono essere generalizzate rispetto al numero di insiemi. Dati n > 0 insiemi Di, D 2 , . . . , Dn, non necessariamente distinti, il prodotto cartesiano di Di, D 2 , . . . , D„, indicato con Di x D 2 x . . . x D„, è costituito dall'insieme delle n-uple (i)j, v2,.. •, vn) tali che v, appartiene a D, , per 1 < i < n. Una relazione matematica sui domini Di, D2,..., Dn è un sottoinsieme del prodotto cartesiano Di x D 2 x . . . x D„. Il numero n delle componenti del prodotto cartesiano (e quindi di ogni n-upla) viene detto grado del prodotto cartesiano e della relazione. Il numero di elementi (cioè di n-uple) della relazione viene chiamato, come di solito nella teoria degli insiemi, cardinalità della relazione. Nella Figura 2.2 sono mostrate le rappresentazioni tabellari del prodotto cartesiano e di una relazione di grado tre sui domini C — {x, >>}, D = [a, b, c} ed E = {3, 5}. La relazione ha cardinalità pari a sei.

1 1 2 2 4 4

a b a b a b

1 1 4

a b b

Figura 2.1 Rappresentazione tabellare di un prodotto cartesiano e di una relazione

X X X

b

X

b

X

c c a a

X

y y y y y y

a a

b b

c c

3 5 X

5 3 5 3 5 3 b 3 5

a a c a c c

X X

y y y

3 5 5 3 3 5

Figura 2.2 Rappresentazione tabellare di un prodotto cartesiano e di una relazione ternari

Le relazioni (e le corrispondenti tabelle) possono essere utilizzate per rappresentare i dati di interesse per qualche applicazione. Per esempio, la relazione nella Figura 2.3 contiene i dati relativi ai risultati di un insieme di partite di calcio. Essa è definita con riferimento a due domini intero e stringa, ognuno dei quali compare due volte. La relazione è infatti un sottoinsieme del prodotto cartesiano: S t r i n g a x Stringa x I n t e r o x I n t e r o

2.1.3 Relazioni con attributi Sulle relazioni e sulle loro rappresentazioni tabellari possiamo fare varie osservazioni. In base alla definizione, una relazione matematica è un insieme di w-uple ordinate (ui, v2,..., vn), con uj e Di, v2 e D2, ..., vn e Dn. Con riferimento all'uso che facciamo delle relazioni per organizzare i dati nelle nostre basi di dati, possiamo dire che ciascuna n-upla contiene dati fra loro collegati, anzi stabilisce un legame fra loro: per esempio la prima n-upla della relazione nella Figura 2.3 stabilisce un legame fra i valori "Juventus," "Lazio," "3," "1", a indicare che il risultato della partita fra Juventus e Lazio è 3 a 1. Possiamo poi ricordare che una relazione è un insieme, quindi:

Juventus Lazio Juventus Roma

Lazio Milan Roma Milan

3 2 1 0

1 0 2 1

Figura 2.3 Una relazione con i risultati di partite di calcio

• non è definito alcun ordinamento fra le «-uple; nelle tabelle che le rappresentano c'è, per necessità, un ordine, ma è "occasionale": due tabelle con le stesse righe, ma in ordine diverso, rappresentano la stessa relazione; . le «-uple di una relazione sono distinte l'una dall'altra, in quanto tra gli elementi di un insieme non possono essere presenti due elementi uguali; quindi una tabella rappresenta una relazione solo se le sue righe sono l'una diversa dall'altra. Al tempo stesso, ciascuna H-upla è, al proprio interno, ordinata: l'/'-esimo valore di ciascuna proviene dall'/-esimo dominio. E cioè definito un ordinamento fra i domini, che è significativo ai fini dell'interpretazione dei dati nelle relazioni: se, nella relazione nella Figura 2.3, scambiassimo il terzo dominio con il quarto, cambieremmo completamente il significato della nostra relazione, in quanto i risultati delle partite verrebbero invertiti. In effetti, questo accade perché nella relazione ciascuno dei due domini intero e stringa compare due volte, e le due occorrenze sono distinte attraverso la posizione: la prima occorrenza del dominio stringa fa riferimento alla squadra di casa e la seconda a quella ospitata; analogamente le due occorrenze del dominio intero. L'ordinamento che abbiamo appena evidenziato fra i domini di una relazione corrisponde in effetti a una caratteristica insoddisfacente del concetto di relazione matematica rispetto alla possibilità di organizzare e utilizzare i dati. Infatti, in vari contesti dell'informatica si tende a privilegiare notazioni non posizionali (quali quelle che permettono, in un linguaggio ad alto livello, di far riferimento ai campi di un record per mezzo di nomi simbolici) rispetto a quelle posizionali (utilizzate per esempio negli array per indicare il primo elemento, il secondo e così via): si tende a utilizzare le notazioni posizionali solo quando l'ordinamento corrisponde a una esigenza intrinseca, come accade per esempio nei problemi di natura matematica, in cui gli array pennettono di rappresentare vettori e matrici in modo ovvio e diretto. Risulta evidente come le informazioni che siamo interessati a organizzare nelle relazioni delle nostre basi di dati abbiano una struttura che si può naturalmente ricondurre a quella dei record: una relazione è sostanzialmente un insieme di record omogenei, cioè definiti sugli stessi campi. Nel caso dei record, a ogni campo è associato un nome: associamo a ciascuna occorrenza di dominio nella relazione un nome, detto attributo, che descrive il "ruolo" giocato dal dominio stesso. Per esempio, per la relazione relativa alle partite, possiamo usare n o m i quali SquadraDiCasa, SquadraOspitata, RetiCasa, RetiOspitata; nella r a p -

presentazione tabellare, utilizziamo gli attributi come intestazioni per le colonne (Figura 2.4); sottolineiamo che, dovendo identificare univocamente le componenti, gli attributi di una relazione (e quindi le intestazioni delle colonne delle tabelle) devono essere diversi l'uno dall'altro. Modificando la definizione di relazione con l'introduzione degli attributi, e prima ancora di dare la definizione formale, possiamo vedere che l'ordinamento degli attributi (e delle colonne nella rappresentazione tabellare) risulta irrilevante: non è più necessario parlare di primo dominio, secondo dominio e così via, è sufficiente far riferimento agli attributi. La Figura 2.5 mostra un'altra rappresentazione tabellare della relazione nella Figura 2.4, con gli attributi (e quindi le colonne) in

SquadraDiCasa

Juventus Lazio Juventus Roma

SquadraOspitata

RetiCasa

RetiOspitata

Lazio Milan Roma Milan

3 2 1 0

1 0 2 1

Figura 2.4 Una relazione con attributi

ordine diverso (secondo lo stile americano in cui la squadra di casa viene indicata dopo quella ospitata). Per formalizzare i concetti, indichiamo con V l'insieme dei domini e specifichiamo la corrispondenza fra attributi e domini, nell'ambito di una relazione, per mezzo di una funzione dom : X V, che associa a ciascun attributo A e X un dominio dom(A) e V. Poi, diciamo che una tupla1 su un insieme di attributi X è una funzione t che associa a ciascun attributo A e X un valore del dominio dom{A). Possiamo quindi dare la nuova definizione di relazione: una relazione su X è un insieme di tuple su X. La differenza fra questa definizione e quella tradizionale di relazione matematica risiede solo nella definizione di tupla: nella relazione matematica abbiamo n-uple i cui elementi sono individuati per posizione, mentre nelle tuple della nuova definizione gli elementi sono individuati per mezzo degli attributi, cioè con una tecnica non posizionale. Introduciamo una notazione che utilizzeremo molto in seguito. Se t è una tupla su X e A e X, allora f[/\] (o t.A) indica il valore di t su A. Per esempio, se t è la prima tupla della relazione 3 nella Figura 2.5, possiamo dire che /[SquadraOspitata] = Lazio

SquadraOspitata

SquadraDiCasa

RetiOspitata

RetiCasa

Lazio Milan Roma Milan

Juventus Lazio Juventus Roma

1

0 2

3 2

1

1

0

Figura 2.5 Un'altra rappresentazione per la relazione nella Figura 2.4

2 Traslitterazione dell'inglese tuple. In italiano sarebbe forse più corretto usare il termine ennupla, ma è ormai diffuso il termine tupla, che permette di sottolineare la differenza con l'usuale concetto di n-upla ordinata visto in precedenza. 3 Più precisamente, dovremmo dire "la tupla rappresentata dalla prima riga della tabella.. ', ma sarebbe un inutile appesantimento.

L a notazione si usa anche per insiemi di attributi, nel qual caso denota tuple: r[SquadraOspitata,RetiOspitata] è una tupla su due attributi.

2.1.4 Relazioni e basi di dati Come già notato, una relazione può essere utilizzata per organizzare dati rilevanti nell'ambito di una applicazione di interesse. Peraltro, di solito non è sufficiente allo scopo una singola relazione: una base di dati è in generale costituita da più relazioni, le cui tuple contengono valori comuni, ove necessario per stabilire corrispondenze. Approfondiamo questo concetto commentando la base di dati nella Figura 2.6: • la prima relazione contiene informazioni relative a un insieme di studenti, con numero di matricola, cognome, nome e data di nascita; • la terza relazione contiene informazioni su alcuni corsi, con codice, titolo e docente; • la seconda relazione contiene informazioni relative a esami: il numero di matricola dello studente, il codice del corso e il voto; questa relazione fa riferimento ai dati contenuti nelle altre due: agli studenti, attraverso i numeri di matricola, e ai corsi, attraverso i relativi codici.

STUDENTI

Matricola

Cognome

Nome

Data di nascita

276545 485745 200768 587614 937653

Rossi Neri Verdi Rossi Bruni

Maria Anna Fabio Luca Mario

25/11/1981 23/04/1982 12/02/1982 10/10/1981 01/12/1981

ESAMI

CORSI

Studente

Voto

Corso

276545 276545 937653 200768

28 27 25 24

01 04 01 04

Codice

Titolo

Docente

01 03 04

Analisi Chimica Chimica

Giani Melli Belli

Figura 2.6 Una base di dati relazionale

La base di dati nella Figura 2.6 mostra una delle caratteristiche fondamentali del modello relazionale, che viene spesso indicata dicendo che esso è "basato su valori": i riferimenti fra dati in relazioni diverse sono rappresentati per mezzo di valori dei domini che compaiono nelle tuple. Va notato che gli altri modelli logici, reticolare e gerarchico (definiti prima del modello relazionale ma tuttora in uso), realizzano le corrispondenze in modo esplicito attraverso puntatori e vengono pertanto detti modelli "basati su record e puntatori". In questo testo non presentiamo in modo articolato tali modelli, ma vogliamo qui brevemente evidenziare la caratteristica fondamentale di un modello ideale basato su record e puntatori. La Figura 2.7 rappresenta la stessa base di dati nella Figura 2.6 con puntatori al posto dei riferimenti realizzati tramite valori (i numeri di matricola degli studenti e i codici dei corsi). Rispetto a un modello basato su record e puntatori, il modello relazionale, basato su valori, presenta diversi vantaggi: • esso richiede di rappresentare solo ciò che è rilevante dal punto di vista dell'applicazione (e quindi dell'utente); i puntatori sono qualcosa di aggiuntivo, legato ad aspetti realizzativi; nei modelli con puntatori, il programmatore delle applicazioni fa riferimento a dati che non sono significativi per l'applicazione; • la rappresentazione logica dei dati (costituita dai soli valori) non fa alcun riferimento a quella fisica, che può anche cambiare nel tempo: il modello relazionale permette quindi di ottenere l'indipendenza fisica dei dati;

STUDENTI

Matricola

Cognome

Nome

Data di nascita

Rossi Neri Verdi Rossi Bruni

Maria Anna Fabio Luca Mario

25/11/1981 23/04/1982 12/02/1982 10/10/1981 01/12/1981

- 276545 485745 - 200768 587614 - 937653 ESAMI

Studente

Voto

Corso

28 27 25 24 CORSI

Codice

Titolo

Docente

01 03 04

Analisi Chimica Chimica

Giani Melli Belli

Figura 2.7 Una base di dati con puntatori

:

• essendo tutta l'informazione contenuta nei valori, è relativamente semplice trasferire i dati da un contesto a un altro (per esempio se si deve trasferire una base di dati da un calcolatore a un altro); in presenza di puntatori, l'operazione è più complessa, perché i puntatori hanno un significato locale al singolo sistema, che non sempre è immediato esportare. A titolo di inciso, vale la pena notare che anche in una base di dati relazionale, a livello fisico, i dati possono essere rappresentati secondo modalità che prevedono l'uso di puntatori. La differenza, rispetto ai modelli basati su puntatore, è nel fatto che qui i puntatori non sono visibili a livello logico. Inoltre, sottolineiamo come nei sistemi di basi di dati a oggetti, che rappresentano una delle direzioni di evoluzione delle basi di dati (come discusso nel secondo volume [5]), vengano introdotti gli identificatori di oggetto, che, pur a un livello di astrazione più alto, presentano alcune delle caratteristiche dei puntatori. Possiamo a questo punto riassumere le definizioni relative al modello relazionale, con un po' di precisione, distinguendo il livello degli schemi da quello delle istanze. • Uno schema di relazione è costituito da un simbolo R, detto nome della relazione, e da un insieme di (nomi di) attributi X = {Ai, A2,..., A„}, il tutto di solito indicato con R(X). A ciascun attributo è associato un dominio, come visto in precedenza. • Uno schema di base di dati è un insieme di schemi di relazione con nomi diversi: R={/?i(XI),/?2(X2),...,/?„(Xn)} I nomi di relazione hanno come scopo principale quello di distinguere le varie relazioni nella base di dati. • Una istanza di relazione (o semplicemente relazione) su uno schema R(X) è un insieme r di tuple su X. • Una istanza di base di dati (o semplicemente base di dati) su uno schema R = {/?i(Xi), R2(X2),..., Rn(Xn)} è un insieme di relazioni r = {ri, r2, • • •, rn), dove ogni ri, per 1 < i < n, è una relazione sullo schema /?,(X,). Per esemplificare, possiamo dire che lo schema della base di dati nella Figura 2.6 è così definito (con opportune definizioni per i domini): R = {STUDENTI (Matricola, Cognome, Nome, Data di nascita), E S A M I (Studente, Voto, Corso), C O R S I (Codice, Titolo, Docente)}

Per comodità, accenniamo brevemente alle convenzioni che adotteremo nel seguito (e che abbiamo già usato nelle definizioni e negli esempi), allo scopo di favorire la sinteticità della notazione senza compromettere la comprensione: • gli attributi (quando non si utilizzeranno nomi significativi dal punto di vista dell'applicazione) verranno indicati con lettere iniziali dell'alfabeto, maiuscole, eventualmente con indici e/o pedici: A, B, C, A', A\, ...

• insiemi di attributi verranno indicati con lettere finali dell'alfabeto, maiuscole: X, Y, Z, X', Xi, . . . ; un insieme in cui si vogliano evidenziare gli attributi componenti verrà denotato dalla giustapposizione dei nomi degli attributi stessi: scriveremo cioè X = ABC anziché X — {A, B,C}\ analogamente, l'unione di insiemi verrà denotata dalla giustapposizione dei relativi nomi: scriveremo XY anziché X U Y\ riunendo le due convenzioni, scriveremo XA anziché X U {A}; • per i nomi di relazione (sempre nel caso in cui si possa o debba fare a meno di nomi significativi) utilizzeremo la R e le lettere contigue, maiuscole: Ri, S, S',...; per le relazioni, gli stessi simboli dei corrispondenti nomi di relazione, ma in lettere minuscole. Per approfondire ancora i concetti fondamentali del modello relazionale, discutiamo un altro paio di esempi. In primo luogo notiamo come, secondo la definizione, siano ammissibili relazioni su un solo attributo. Ciò può avere senso in particolare in basi di dati su più relazioni, in cui la relazione su singolo attributo contiene valori che appaiono come valori di un attributo di un'altra relazione. Per esempio, in una base di dati in cui sia presente la relazione STUDENTI della Figura 2.6, si può utilizzare (Figura 2.8) un'altra relazione sul solo attributo Matricola per indicare gli studenti lavoratori (attraverso i relativi numeri di matricola, che devono apparire nella relazione STUDENTI).

Discutiamo ora un esempio un po' più complesso, che mostra come, sia pur indirettamente, il modello relazionale permetta di rappresentare informazione strutturata in modo articolato. Nella Figura 2.9 sono schematizzate tre ricevute fiscali emesse da un ristorante. Esse hanno una struttura che prevede (a parte le frasi prestampate che abbiamo riportato in grassetto) alcune informazioni fisse (numero, data e totale) e un numero di righe variabile, ognuna relativa a un insieme di portate omogenee (con quantità, descrizione e importo complessivo). Poiché le nostre relazioni hanno una struttura fissa, non è possibile rappresentare l'insieme delle ricevute con un'unica relazione (non sarebbe possibile rappresentare le righe in numero non predeterminato). Possiamo però rappresentare le relative informazioni per mezzo di due relazioni, come mostrato nella Figura 2.10: la relazione R I C E V U T E contiene i dati

STUDENTI Matr.

Cognome

Nome

Data di nascita

276545 485745 200768 587614 937653

Rossi Neri Verdi Rossi Bruni

Maria Anna Fabio Luca Mario

25/11/1981 23/04/1982 12/02/1982 10/10/1981 01/12/1981

Figura 2.8 Una relazione su un solo attributo

LAVORATORI

"DA M A R I O "

3 2 3 2

"DA M A R I O "

"DA M A R I O "

Ricevuta n. 1357

Ricevuta n. 2334

del 5/5/08

del 4/7/08

coperti antipasti primi bistecche

6,00 12,00 27,00 36.00

Totale

81,00

2 1

2 2 2

Ricevuta n. 3002 del 4/8/08

coperti antipasti primi orate caffè

4,00 6,00 15,00 50,00 3,00

Totale

78,00

3 2 3 1 1 2

coperti antipasti primi orate caprese caffè

6,00 14,00 20,00 25,00 8,00 3,00

Totale

76,00

Figura 2.9 Alcune ricevute fiscali

presenti una sola volta in ciascuna ricevuta (numero, data e totale) e la relazione D E T T A G L I O contiene le varie righe di ciascuna ricevuta (con quantità, descrizione e importo complessivo), associate alla ricevuta stessa tramite il relativo numero.

E opportuno notare che la base di dati nella Figura 2.10 rappresenta correttamente le ricevute solo se sono vere le due condizioni seguenti:

DETTAGLIO

RICEVUTE Num

Data

1357 2334 3002

5/5/08 4/7/08 4/8/08

Totale

81,00 78,00 76,00

Num

Q.tà

Descr

Costo

1357 1357 1357 1357 2334 2334 2334 2334 2334 3002 3002 3002 3002 3002 3002

3 2 3 2 2 1 2 2 2 3 2 3 1 1 2

coperti antipasti primi bistecche coperti antipasti primi orate caffé coperti antipasti primi orate caprese caffé

6,00 12,00 27,00 36,00 4,00 6,00 15,00 50,00 3,00 6,00 14,00 20,00 25,00 8,00 3,00

Figura 2.10 Una base di dati per le ricevute fiscali nella Figura 2.9

RICEVUTE Num

Data

1357 2334 3002

5/5/08 4/7/08 4/8/08

Totale

81,00 78,00 76,00

Num

Riga

Q.tà

Descr

Costo

1357 1357 1357 1357 2334 2334 2334 2334 2334 3002 3002 3002 3002 3002 3002

1 2 3 4 1 2 3 4 5 1 2 3 4 5 6

3 2 3 2 2 1 2 2 2 3 2 3 1 1 2

coperti antipasti primi bistecche coperti antipasti primi orate caffè coperti antipasti primi orate caprese caffè

6,00 12,00 27,00 36,00 4,00 6,00 15,00 50,00 3,00 6,00 14,00 20,00 25,00 8,00 3,00

Figura 2.11 Un'altra base di dati per le ricevute fiscali

• non interessa mantenere traccia dell'ordine con cui le righe compaiono in ciascuna ricevuta: infatti, poiché nessun ordinamento è definito fra le tuple di una relazione, le tuple di DETTAGLIO non sono in alcun modo ordinate; • in una ricevuta non compaiono due righe uguali (il che potrebbe accadere in presenza di ordinazioni diverse relative alle stesse pietanze con le stesse quantità). Altrimenti, si può risolvere il problema aggiungendo un attributo, che indica la posizione della riga sulla ricevuta (Figura 2.11): in questo modo è sempre possibile ricostruire perfettamente il contenuto di tutte le ricevute. In generale, possiamo dire che la soluzione di Figura 2.10 è da preferirsi quando le informazioni sulla ricevuta interessano solo in quanto tali (e nelle ricevute non vi sono righe ripetute), mentre quella di Figura 2.11 pennette di tenere traccia dell'effettiva impaginazione di ciascuna ricevuta. L'esempio ci permette quindi di notare che, anche in una stessa situazione, i dati da rappresentare nella base di dati possono essere diversi a seconda degli specifici obiettivi che ci si prefigge.

2.1.5 Informazione incompleta e valori nulli La struttura del modello relazionale, come discussa nei paragrafi precedenti, è indubbiamente molto semplice e potente. Al tempo stesso, essa impone però un certo grado di rigidità, in quanto le informazioni devono essere rappresentate per mezzo di tuple di dati omogenee: in particolare, in ogni relazione possiamo rappresentare solo tuple corrispondenti allo schema della relazione stessa. In effetti,

in molti casi, i dati disponibili possono non corrispondere esattamente al formato previsto. Per esempio, in una relazione sullo schema: PERSONE(Cognome, Nome, Indirizzo,Telefono)

il valore dell'attributo Telefono potrebbe non essere disponibile per tutte le tuple. Vale la pena notare che non sarebbe corretto utilizzare un valore del dominio per rappresentare l'assenza di informazione, in quanto si potrebbe in tal modo generare confusione. In questo caso, supponendo i numeri telefonici rappresentati per mezzo di interi, potremmo per esempio utilizzare lo zero per indicare l'assenza di un valore significativo. In generale, però, questa scelta non risulta soddisfacente, per due motivi. In primo luogo, essa richiede l'esistenza di un valore del dominio mai utilizzato per valori significativi: nel caso dei numeri di telefono, lo zero è chiaramente distinguibile, ma in altri casi non esiste un valore disponibile allo scopo; per esempio, in un attributo che rappresenti la data di nascita e che utilizzi come dominio un tipo Data correttamente definito, non esistono elementi "non utilizzati" per valori significativi e quindi utilizzabili per denotare assenza di informazione. In secondo luogo, l'uso di valori del dominio può generare confusione: la distinzione fra valori "veri" e valori fittizi è nascosta, e quindi i programmi che accedono alla base di dati devono tenerne conto, distinguendo opportunamente (e tenendo conto di quali sono, in ciascun caso, i valori fittizi). Per rappresentare in modo semplice, ma al tempo stesso comodo, la non disponibilità di valori, il concetto di relazione viene di solito esteso prevedendo che una tupla possa assumere, su ciascun attributo, o un valore del dominio, come visto finora, oppure un valore speciale, detto valore nullo, che denota appunto l'assenza di informazione, ma è un valore aggiuntivo rispetto a quelli del dominio, e ben distinto da essi. Nelle rappresentazioni tabellari, utilizzeremo per il valore nullo il simbolo NULL, come nella Figura 2.12. Con riferimento alla tabella in figura, possiamo notare come in effetti i tre valori nulli che compaiono in essa siano dovuti a motivazioni diverse, come segue. • Firenze è capoluogo di provincia e quindi ha certamente una prefettura. Al momento, non disponiamo del suo indirizzo. Il valore nullo sostituisce un valore ordinario, non noto alla base di dati: per questo diciamo che si tratta di un valore sconosciuto. • Tivoli non è capoluogo di provincia e perciò non ha una prefettura. Quindi l'attributo IndirizzoPrefettura non può avere un valore per questa tupla. Il valore

Città

IndirizzoPrefettura

Roma Firenze Tivoli Olbia-Tempio

Via Quattro Novembre NULL NULL NULL

Figura 2.12 Una relazione con valori nulli

nullo denota l'inapplicabilità dell'attributo o l'inesistenza del valore: il valore è inesistente. • La provincia di Olbia-Tempio, nel momento in cui scriviamo, è da poco stata istituita e non sappiamo se la prefettura sia già stata costituita, né conosciamo il suo indirizzo (già operativo o previsto). In sostanza, non sappiamo se il valore esista e, in caso affermativo, non lo conosciamo. Sostanzialmente, ci troviamo in una situazione che corrisponde alla disgiunzione logica (l'"or") delle due precedenti: il valore è inesistente oppure sconosciuto. Questo tipo di valore nullo viene di solito chiamato senza informazione, perché non ci dice assolutamente niente: il valore può esistere o non esistere, e se esiste non sappiamo quale sia. Nei sistemi di basi di dati relazionali, è di solito prevista una gestione molto semplice, ma tutto sommato efficace, del valore nullo, sul quale non viene fatta alcuna ipotesi e quindi in pratica ci si trova nell'ultimo caso, quello del valore senza informazione. Per una ulteriore riflessione sui valori nulli, consideriamo la base di dati nella Figura 2.13, che è definita sullo stesso schema della base di dati di Figura 2.6. Il valore nullo sulla data di nascita nella prima tupla della relazione STUDENTI è tutto sommato ammissibile, perché si può pensare che l'informazione non sia in questo contesto essenziale. Viceversa, un valore nullo sul numero di matricola o sul codice di un corso genera problemi maggiori, in quanto questi valori, come abbiamo discusso con riferimento alla Figura 2.6, sono utilizzati per stabilire correlazioni fra tuple di relazioni diverse. Poi, la presenza di valori nulli nella relazione ESAMI rende addirittura inutilizzabili le informazioni: per esempio, la seconda tupla, con il solo voto e due valori nulli, non fornisce alcuna informazione utile. Infine, la presenza di molteplici valori nulli in una relazione può addirittura generare dubbi sull'effettiva significatività e identità delle tuple: le ultime due tuple della relazione CORSI possono essere diverse o addirittura coincidere! E eviden-

STUDENTI Matricola

Cognome

Nome

Data di nascita

276545

Rossi Neri Verdi

Maria Anna Fabio

23/04/1982 12/02/1982

NULL NULL

ESAMI Studente

NULL

CORSI Voto

Corso

Codice

Titolo

Docente

276545

28

01

01

Analisi

Giani

NULL 200768

27 24

NULL NULL

03 NULL

Chimica Chimica

NULL Belli

Figura 2.13 Una base di dati con molti valori nulli

te quindi come sia necessario controllare opportunamente la presenza dei valori nulli nelle nostre relazioni: solo alcune configurazioni devono essere ammesse. In genere, quando si definisce una relazione, è possibile specificare che i nulli sono ammessi solo su alcuni attributi e non su altri. Alla fine del Paragrafo 2.2 vedremo quale possa essere un criterio fondamentale per individuare alcuni attributi su cui è essenziale evitare la presenza di valori nulli.

2.2 Vincoli di integrità Le strutture del modello relazionale ci permettono di organizzare le informazioni di interesse per le nostre applicazioni. In molti casi, però, non è vero che qualsiasi insieme di tuple sullo schema rappresenti informazioni corrette per l'applicazione. Abbiamo già discusso in breve il problema relativamente alla presenza di valori nulli. Ora, approfondiamo il problema con riferimento anche a relazioni prive di valori nulli. Consideriamo per esempio la base di dati nella Figura 2.14 e notiamo in essa varie situazioni che in pratica non si dovrebbero presentare. • Nella prima tupla della relazione ESAMI abbiamo un voto pari a 36 che, nel sistema italiano, non è ammissibile, in quanto i voti devono essere compresi fra 0 e 30 (o, con riferimento al superamento dell'esame, fra 18 e 30).

STUDENTI Matricola

Cognome

Nome

Data di nascita

200768 937653 937653

Verdi Rossi

Fabio Luca Mario

12/02/1982 10/10/1981 01/12/1981

Bruni

ESAMI Studente

Voto

Lode

Corso

200768 937653 937653 276545

36 28 30 25

lode lode

05 01 04 01

CORSI Codice

Titolo

Docente

01 03 04

Analisi Chimica Chimica

Giani Melli Belli

Figura 2.14 Una base di dati con informazioni scorrette

• Nella seconda tupla ancora della relazione ESAMI viene indicato che è stata attribuita la lode in un esame in cui il voto è 28, il che è impossibile: la lode può essere attribuita solo se il voto è 30. • Le ultime due tuple della relazione STUDENTI contengono informazioni su due studenti diversi con lo stesso numero di matricola: ancora una situazione impossibile, in quanto il numero di matricola serve appunto a identificare univocamente gli studenti. • La quarta tupla della relazione ESAMI presenta, per l'attributo Studente, un valore che non compare fra i numeri di matricola nella relazione STUDENTI: anche questa è una situazione indesiderabile, poiché i numeri di matricola ci forniscono informazioni solo come tramite verso le corrispondenti tuple della relazione STUDENTI. Analogamente, la prima tupla presenta un codice di corso che non compare nella relazione CORSI. In una base di dati, è opportuno evitare situazioni come quelle appena descritte. Allo scopo, è stato introdotto il concetto di vincolo di integrità, come proprietà che deve essere soddisfatta dalle istanze che rappresentano informazioni corrette per l'applicazione. Ogni vincolo può essere visto come un predicato che associa a ogni istanza il valore vero o falso. Se il predicato assume il valore vero diciamo che l'istanza soddisfa il vincolo. In generale, a uno schema di base di dati associamo un insieme di vincoli e consideriamo corrette (o lecite, o ammissibili) le istanze che soddisfano tutti i vincoli. In ciascuno dei quattro casi sopra discussi potrebbe essere introdotto un vincolo che vieti la situazione indesiderata. E possibile classificare i vincoli a seconda degli elementi di una base di dati che ne sono coinvolti. Distinguiamo due categorie, la prima delle quali ha alcuni casi particolari. • Un vincolo è intrarelazionale se il suo soddisfacimento è definito rispetto a singole relazioni della base di dati; i primi tre casi sopra discussi corrispondono a vincoli intrarelazionali; talvolta, il coinvolgimento riguarda le tuple (o addirittura i valori) separatamente le une dalle altre: - un vincolo di tupla è un vincolo che può essere valutato su ciascuna tupla indipendentemente dalle altre: i vincoli relativi ai primi due casi rientrano in questa categoria; - come caso ancora più specifico, un vincolo definito con riferimento a singoli valori (è il caso del primo esempio, in cui sono ammessi solo valori dell'attributo Voto compresi fra 18 e 30) viene detto vincolo su valori o vincolo di dominio, in quanto impone una restrizione sul dominio dell'attributo. • Un vincolo è interrelazionale se coinvolge più relazioni; è questo il caso del quarto esempio, in cui la situazione indesiderata può essere vietata richiedendo che un numero di matricola compaia nella relazione ESAMI solo se compare nella relazione STUDENTI. Nei paragrafi seguenti esaminiamo con un certo dettaglio tre classi di vincoli molto importanti:

. una classe interessante di vincoli di tupla; • i vincoli di chiave, che sono i più importanti vincoli intrarelazionali; • i vincoli di integrità referenziale, che sono i vincoli interrelazionali di maggiore interesse.

2.2.1 Vincoli di tupla Come abbiamo detto, i vincoli di tupla esprimono condizioni sui valori di ciascuna tupla, indipendentemente dalle altre tuple. Una possibile sintassi per esprimere vincoli di questo tipo è quella che permette di definire espressioni booleane (cioè con connettivi AND, OR e NOT) con atomi che confrontano (con gli operatori di uguaglianza, disuguaglianza e ordinamento) valori di attributo o espressioni aritmetiche su valori di attributo. I vincoli violati individuati nei primi due esempi della lista del Paragrafo 2.2 potrebbero essere descritti con le seguenti espressioni: (Voto > 18) AND (Voto < 30) (NOT (Lode = ' l o d e ' ) ) OR (Voto = 3 0 )

In particolare, il secondo vincolo indica che è ammissibile la lode solo se il voto è pari a 30 (dicendo che o non c'è la lode, oppure il voto è pari a 30). Il primo vincolo è in effetti un vincolo di dominio in quanto coinvolge un solo attributo. La definizione che abbiamo dato ammette anche espressioni più complesse, purché definite sui valori delle singole tuple. Per esempio, su una relazione sullo schema: PAGAMENTI(Data, Importo, Ritenute, Netto)

è possibile definire il vincolo che impone, come naturale, che il netto sia pari alla differenza fra l'importo originario e le ritenute, nel modo seguente: Netto = Importo - Ritenute

2.2.2 Chiavi In questo paragrafo discutiamo i vincoli di chiave, che sono senz'altro i più importanti del modello relazionale; potremmo addirittura affermare che senza di essi il modello stesso non avrebbe senso. Cominciamo con un esempio. Nella relazione della Figura 2.15 possiamo notare che i valori delle varie tuple sull'attributo Matricola sono tutti diversi l'uno dall'altro: come già notato più volte, ribadiamo che il valore della matricola identifica univocamente gli studenti; a suo tempo il concetto stesso di numero di matricola fu introdotto nelle università proprio per avere uno strumento semplice ed efficace per far riferimento agli studenti in modo non ambiguo. Analogamente, possiamo notare che nella relazione non vi sono coppie di tuple con gli stessi valori su ciascuno dei tre attributi Cognome, Nome

Matricola

Cognome

Nome

Nascita

Corso

4328 6328 4766 4856 5536

Rossi Rossi Rossi Neri Neri

Luigi Dario Luca Luca Luca

29/04/84 29/04/84 01/05/86 01/05/86 05/03/83

Ing. Informatica Ing. Informatica Ing. Civile Ing. Meccanica Ing. Meccanica

Figura 2.15 Una relazione per la discussione delle chiavi

e Nascita: anche i dati anagrafici identificano univocamente le persone. 4 Anche altri insiemi di attributi identificano univocamente le tuple della relazione nella Figura 2.15: per esempio, Matricola e Corso, come è in effetti ovvio, visto che Matricola è da solo sufficiente. Intuitivamente, una chiave è un insieme di attributi utilizzato per identificare univocamente le tuple di una relazione. Per formalizzare la definizione, procediamo in due passi: • un insieme K di attributi è superchiave di una relazione r se r non contiene due tuple distinte t\ e t2 con MA'] = t2[K\, • K è chiave di r se è una superchiave minimale di r (cioè non esiste un'altra superchiave K' di r che sia contenuta in K come sottoinsieme proprio). Nell'esempio: • l'insieme {Matricola} è superchiave; è anche una superchiave minimale, in quanto contiene un solo attributo (l'insieme vuoto non è in grado di identificare tuple), quindi {Matricola} è una chiave; • l'insieme {Cognome, Nome, Nascita} è superchiave; inoltre, nessuno dei suoi sottoinsiemi è superchiave: infatti esistono due tuple (la prima e la seconda) u g u a l i su C o g n o m e e Nascita, d u e (le u l t i m e ) u g u a l i su C o g n o m e e N o m e e

due (la terza e la quarta) uguali su Nome e Nascita; quindi {Cognome, Nome, Nascita} è un'altra chiave; • l'insieme {Matricola, Corso} è superchiave, come già discusso, ma non è una superchiave minimale, perché esiste un suo sottoinsieme proprio, {Matricola}, esso stesso superchiave minimale e quindi {Matricola, Corso} non è una chiave; • l'insieme {Nome, Corso} non è superchiave, perché nella relazione compaiono due tuple, le ultime due, fra loro uguali sia su Nome sia su Corso. Per approfondire la discussione, esaminiamo un'altra relazione, quella nella Figura 2.16. Essa non contiene tuple fra loro uguali sia su Cognome sia su Corso. 4

Per non appesantire l'esempio, assumiamo qui che cognome, nome e data di nascita siano sufficienti a identificare univocamente le persone, il che in generale non è vero.

Matricola

6328 4766 4856 5536

Cognome

Rossi Rossi Neri Neri

Nome

Nascita

Corso

Dario Luca Luca Luca

29/04/84 01/05/86 01/05/86 05/03/83

Ing. Informatica Ing. Civile Ing. Meccanica Ing. Civile

Figura 2.16 Un'altra relazione per la discussione delle chiavi

Quindi, per questa relazione, l'insieme {Cognome, Corso} è superchiave. Poiché vi sono tuple uguali su Cognome (le prime due) e su Corso (la seconda e la quarta), tale insieme è superchiave minimale e cioè chiave. Ora, in questa relazione, Cognome e Corso identificano univocamente le tuple; ma possiamo dire che questo è vero in generale? Certamente no, in quanto possono benissimo esistere studenti con uguale cognome iscritti allo stesso corso di studio. In un certo senso, possiamo quindi dire che {Cognome, Corso} è "casualmente" una chiave per la relazione nella Figura 2.16, mentre a noi interessano le chiavi corrispondenti a vincoli di integrità, soddisfatti da tutte le relazioni lecite su un certo schema. In effetti, definendo uno schema, noi associamo a esso i vincoli di interesse, corrispondenti a proprietà del mondo reale le cui informazioni vengono rappresentate per mezzo della nostra base di dati. I vincoli sono cioè definiti a livello di schema, con riferimento a tutte le istanze: consideriamo corrette solo le istanze che soddisfano tutti i vincoli. Un'istanza corretta può poi soddisfare altri vincoli oltre a quelli definiti sullo schema. Per esempio, a uno schema: STUDENTI( Matricola, Cognome, Nome, Nascita,Corso)

vanno associati i vincoli che impongono come chiavi i due insiemi di attributi sopra discussi: {Matricola} {Cognome, Nome, Nascita}

Entrambe le relazioni nelle Figure 2.15 e 2.16 soddisfano tutti e due i vincoli; la seconda soddisfa anche ("per caso," come abbiamo detto) il vincolo secondo cui {Cognome,Corso} è un'altra chiave. Possiamo ora fare alcune riflessioni sul concetto di chiave, che giustificano l'importanza a esso attribuita. In primo luogo, possiamo notare come ciascuna relazione e ciascuno schema di relazione abbiano sempre una chiave. Una relazione è un insieme, quindi, come più volte ribadito, è costituita di elementi fra loro diversi; di conseguenza, per ogni relazione r ( X ) , l'insieme X di tutti gli attributi su cui è definita è senz'altro una superchiave per essa. Ora, i casi sono due: o tale insieme è anche chiave, nel qual caso confermiamo l'esistenza della chiave stessa, oppure non è chiave, perché esiste un'altra superchiave in esso contenuta; allora possiamo procedere ricorsivamente, ripetendo il ragionamento su quest'ultimo insieme, e così via; poiché l'insieme di attributi su cui è definita una relazione e

finito, il processo termina in un numero finito di passi con una superchiave minimale. Quindi, possiamo affermare con certezza che ogni relazione ha una chiave. Lo stesso ragionamento può essere svolto a livello di schema di relazione: l'insieme di tutti gli attributi è superchiave per ciascuna relazione, quindi lo è per ciascuna relazione lecita; la ricerca di superchiavi minimali procede poi come sopra. Il fatto che su ciascuno schema di relazione possa essere definita almeno una chiave garantisce l'accessibilità a tutti i valori di una base di dati e la loro univoca identificabilità. Inoltre, permette di stabilire efficacemente quelle corrispondenze fra dati contenuti in relazioni diverse che caratterizzano il modello relazionale come "modello basato su valori." Riconsideriamo l'esempio nella Figura 2.6. Nella relazione ESAMI, si fa riferimento agli studenti attraverso i numeri di matricola e ai corsi attraverso i relativi codici: in effetti, Matricola è la chiave della relazione STUDENTI e Codice è la chiave della relazione CORSI. I valori attraverso cui vengono stabilite le corrispondenze fra tuple di relazioni diverse sono valori delle chiavi delle relazioni cui si fa riferimento dall'esterno.

2.2.3 Chiavi e valori nulli Possiamo ora riprendere il discorso avviato alla fine del Paragrafo 2.1.5 sulla necessità di evitare la proliferazione di valori nulli nelle nostre relazioni. In particolare, notiamo che in presenza di valori nulli non è più vero che, come abbiamo invece affermato più volte, i valori delle chiavi permettono di identificare univocamente le tuple delle relazioni e di stabilire riferimenti fra tuple di relazioni diverse. Esaminando allo scopo la relazione nella Figura 2.17, definita sullo stesso schema della relazione nella Figura 2.16 (quindi con due chiavi, una composta dal solo attributo Matricola e l'altra dagli attributi Cognome, Nome e Nascita), notiamo problemi di due tipi. La prima tupla ha valori nulli su Matricola e Nascita e perciò su almeno un attributo di ciascuna chiave: questa tupla non è identificabile in alcun modo; se vogliamo inserire nella base di dati un'altra tupla relativa a uno studente di nome Mario Rossi, non possiamo sapere se ci stiamo in effetti riferendo allo stesso studente oppure a un altro. Inoltre, non è possibile, in altre relazioni della base di dati, fare riferimento a questa tupla, visto che ciò andrebbe fatto attraverso il valore di una chiave. Anche le ultime due tuple nella figura presentano un problema: nonostante ciascuna abbia una chiave completamente specificata

Matricola

Cognome

Nome

NULL

Rossi Rossi Neri Neri

Mario Luca Luca Luca

4766 4856 NULL

Nascita

Corso

NULL

Ing. Informatica Ing. Civile

01/05/86 NULL

NULL

05/03/83

Ing. Civile

Figura 2.17 Una relazione con valori nulli su t u t t e le chiavi

Matricola

Cognome

Nome

3976 4766 4856 5591

Rossi Rossi Neri Neri

Mario Luca Luca Luca

Nascita

Corso

NULL

Ing. Informatica Ing. Civile

01/05/86 NULL

NULL

05/03/83

Ing. Civile

Figura 2.18 Una relazione con chiave primaria

(grazie al valore su M a t r i c o l a nella terza tupia e ai valori su Cognome, Nome e Nascita nell'ultima), la presenza di valori nulli rende impossibile capire se le due tupie facciano riferimento allo stesso studente Luca Neri oppure a due studenti omonimi. L'esempio ci suggerisce quindi la necessità di porre dei limiti alla presenza di valori nulli nelle chiavi delle relazioni. In pratica, si adotta una soluzione semplice, che permette di garantire l'identificazione univoca di tutte le tupie e la possibilità di far riferimento a esse da parte di altre relazioni: su una delle chiavi (detta la chiave primaria) si vieta la presenza di valori nulli; sulle altre, i valori nulli sono in genere (salvo necessità specifiche) ammessi. Gli attributi che costituiscono la chiave primaria vengono spesso evidenziati attraverso la sottolineatura, come mostrato nella Figura 2.18 con la sottolineatura dell'attributo Matricola. La maggior parte dei riferimenti tra relazioni vengono realizzati attraverso i valori della chiave primaria. È opportuno notare che in quasi tutti i casi reali è possibile trovare attributi i cui valori sono identificanti e sempre disponibili. Quando ciò non accada, è necessario introdurre un attributo aggiuntivo, un codice, probabilmente non significativo dal punto di vista dell'applicazione, che viene in qualche modo generato e attribuito a ciascuna tupia all'atto dell'inserimento. Tra l'altro, si può dire che molti codici identificativi (quali per esempio il numero di matricola, il codice fiscale, il numero di targa) siano stati introdotti in passato, prima dell'invenzione o della diffusione delle basi di dati, proprio per garantire l'identificazione univoca dei soggetti di un dominio (rispettivamente gli studenti, i contribuenti, le automobili) e per favorire il riferimento a essi: esattamente gli obiettivi delle chiavi.

2.2.4 Vincoli di integrità referenziale Per discutere la più importante classe di vincoli interrelazionali, consideriamo la base di dati in Figura 2.19. In essa, la prima relazione contiene informazioni relative a un insieme di infrazioni al codice della strada, la seconda agli agenti di polizia che le hanno rilevate e la terza a un insieme di autoveicoli. 5 Le informazioni della relazione INFRAZIONI sono rese significative e complete attraverso il

5

Utilizziamo la vecchia struttura delle targhe automobilistiche, con la sigla della provincia, perché ci permette di svolgere considerazioni interessanti sulle chiavi composte da più attributi.

INFRAZIONI

Codice

Data

Agente

Articolo

143256 987554 987557 630876 539856

25/10/08 26/10/08 26/10/08 15/10/08 12/10/08

567 456 456 456 567

44 34 34 53 44

AGENTI

AUTO

rProv

Numero

RM RM RM MI MI

Matricola

CF

Cognome

Nome

567 456 638

RSSM... NREL... NREP...

Rossi Neri Neri

Mario Luigi Piero

Prov

Numero

Proprietario

Indirizzo

RM RM RM MI

2F7643 1A2396 4E5432 2F7643

Verdi Piero Verdi Piero Bini Luca Luci Gino

Via Tigli Via Tigli Via Aceri Via Aceri

4E5432 4E5432 2F7643 2F7643 2F7643

Figura 2.19 Una base di dati con vincoli di integrità referenziale

riferimento alle altre due relazioni: alla relazione AGENTI, per il tramite dell'attributo Agente, che contiene numeri di matricola di agenti corrispondenti alla chiave primaria della relazione AGENTI, e alla relazione AUTO, per mezzo degli attributi Prov e Numero, che contengono valori degli omonimi attributi che formano la chiave primaria della relazione AUTO. I riferimenti sono significativi in quanto i valori nella relazione INFRAZIONI sono uguali a valori effettivamente presenti nelle altre due: se un valore di Agente in INFRAZIONI non compare come valore della chiave di AGENTI, allora il riferimento non è efficace. Nell'esempio, tutti i riferimenti sono in effetti utilizzabili. Un vincolo di integrità referenziale (chiamato nella letteratura in inglese foreign key o referential integrity constraint) fra un insieme di attributi X di una relazione R\ e un'altra relazione Ri è soddisfatto se i valori su X di ciascuna tupla dell'istanza di R\ compaiono come valori della chiave (primaria) dell'istanza di R2. La definizione precisa richiede un po' di attenzione, in particolare nel caso in cui la chiave della relazione riferita sia composta di più attributi e nel caso in cui vi siano più chiavi. Procediamo gradualmente, vedendo prima il caso in cui la chiave di R2 è unica e composta di un solo attributo B (e quindi l'insieme X è a sua volta costituito da un solo attributo A): allora, il vincolo di integrità referenziale fra l'attributo A di Ri e la relazione R2 è soddisfatto se, per ogni tupla ti in R i per cui fi [A] non è nullo, esiste una tupla t2 in R2 tale che t\[A] = t2[B]. Nel caso più generale, dobbiamo fare attenzione al fatto che ciascuno degli attributi in X deve corrispondere a un preciso attributo della chiave primaria A" di R2. Allo

scopo, è necessario specificare un ordinamento sia nell'insieme X sia in K. Indicando gli attributi in ordine, X = AXA2 . • • Ap e K = B\B2 ... Bp, i\ vincolo è soddisfatto se per ogni tupla in /?, senza nulli su X esiste una tupla t2 in R2 con t\[Ai] = t2[Bi~\, per ogni i compreso fra 1 e p. Sullo schema della base di dati nella Figura 2.19 ha senso definire i vincoli di integrità referenziale: • f r a l ' a t t r i b u t o A g e n t e d e l l a r e l a z i o n e INFRAZIONI e la r e l a z i o n e A G E N T I ; • f r a gli a t t r i b u t i Prov e Numero d i INFRAZIONI e la r e l a z i o n e A U T O , in c u i

l'ordine degli attributi nella chiave preveda prima Prov e poi Numero.

La base di dati nella Figura 2.19 soddisfa entrambi i vincoli, mentre la base di dati nella Figura 2.20 li viola entrambi: il primo perché AGENTI non contiene nessuna tupla con valore di Matricola pari a 456, e il secondo perché AUTO non contiene nessuna tupla con valore ' R M ' su Prov e '2F7643' su Numero (notiamo che esistono una tupla con valore ' R M ' su Prov e un'altra con valore '2F7643' su Numero, ma questo non è sufficiente, perché è richiesto che ci sia una tupla con entrambi i valori: solo in questo modo, infatti, i due valori possono far riferimento a una tupla della relazione AUTO). Relativamente al secondo vincolo, notiamo come il ragionamento sull'ordine degli attributi possa apparire pesante, visto che la corrispondenza può, almeno in questo caso, essere realizzata per mezzo dei nomi degli attributi stessi. In generale, però, questo può non accadere, quindi l'ordinamento è essenziale. Consideriamo per esempio una base di dati contenente informazioni sui veicoli coinvolti in incidenti stradali. In particolare, supponiamo di voler includere in una relazione,

INFRAZIONI

Codice

Data

Agente

Articolo

Prov

Numero

987554 630876

26/10/08 15/10/08

456 456

34 53

RM

2F7643 4E5432

AGENTI

FI

Matricola

CF

Cognome

Nome

567 638

RSSM... NREP...

Rossi Neri

Mario Piero

Prov

Numero

Proprietario

Indirizzo

RM FI MI

1A2396 4E5432 2F7643

Verdi Piero Bini Luca Luci Gino

Via Tigli Via Aceri Via Noci

Figura 2.20 Una base di dati che viola vincoli di integrità referenziale

INCIDENTI

Codice

Provi

Numerol

Prov2

Numero2

6207 6974

RM FI

2F7643 4E5432

FI FI

T39275 T39275

Prov

Numero

Proprietario

Indirizzo

RM FI FI RM

1A2396 4E5432 T39275 2F7643

Verdi Piero Bini Luca Bitti Piero Luci Gino

Via Tigli Via Aceri Via Pini Via Noci

Figura 2.21 Una base di dati con due vincoli di integrità referenziale simili

insieme ad altre informazioni, i numeri di targa dei due veicoli coinvolti. 6 Ovviamente, dovremo avere due coppie di attributi, che non potranno avere gli stessi nomi. Per esempio, lo schema potrebbe essere: LNCIDENTI(Codice, P r o v i , Numero - !, Prov2, Numero2, ...)

In questo caso, non sarà ovviamente possibile stabilire la corrispondenza nel vincolo di integrità referenziale verso la relazione AUTO per mezzo dei nomi degli attributi, in quanto essi sono diversi da quelli della chiave primaria di AUTO. Solo attraverso l'ordinamento diventa possibile specificare che il riferimento associa P r o v i ( a t t r i b u t o di INCIDENTI) a Prov ( a t t r i b u t o n e l l a c h i a v e di A U T O ) e Numer o 1 a Numero e, a n a l o g a m e n t e , Prov2 a Prov e Numero2 a Numero. L a b a s e di

dati in Figura 2.21 soddisfa i due vincoli in questione, mentre quella in Figura 2.22 soddisfa quello relativo a Provi e Numerol e viola l'altro, perché nella relazione AUTO non c'è nessun veicolo targato FI T39275.

Codice

Provi

Numerol

Prov2

Numero2

6207 6974

RM FI

2F7643 4E5432

FI FI

T39275 T39275

Prov

Numero

Proprietario

Indirizzo

RM FI RM

1A2396 4E5432 2F7643

Verdi Piero Bini Luca Luci Gino

Via Tigli Via Aceri Via Noci

Figura 2.22 Una base di dati che viola un vincolo di integrità referenziale

^Supponiamo per semplicità che i veicoli coinvolti siano solo due.

Un'ultima considerazione può essere utile riguardo a relazioni con più chiavi. In questo caso, come abbiamo detto, è opportuno che una delle chiavi sia evidenziata come primaria, ed è ragionevole che i riferimenti siano diretti verso di essa: per questo motivo, nella specifica dei vincoli di integrità referenziale, abbiamo potuto omettere la citazione esplicita degli attributi che compongono la chiave primaria. Peraltro, va notato che non tutti i sistemi di gestione di basi di dati oggi sul mercato permettono di indicare esplicitamente la chiave primaria: alcuni permettono anche di specificare più chiavi, ma non di evidenziarne una come primaria. In questi casi, il vincolo di integrità referenziale deve indicare esplicitamente gli attributi che compongono la chiave cui si fa riferimento. Per esempio, consideriamo una base di dati sullo schema LMPIEGATI(Matricola, Cognome, Nome, Dipartimento) DIPARTIMENTI(Codice,Nome,Sede)

in cui la relazione DIPARTIMENTI sia identificata dall'attributo Codice e, separatamente, dall'attributo Nome (non esistono due dipartimenti con lo stesso codice e non esistono due dipartimenti con lo stesso nome). Metodologicamente, abbiamo detto che è opportuno che una delle due chiavi, per esempio Codice, sia individuata come primaria e utilizzata per stabilire i riferimenti. Se però il sistema non prevede il concetto di chiave primaria, il vincolo deve essere espresso indicando esplicitamente gli attributi; dovremo quindi dire che esiste un vincolo di integrità referenziale fra l'attributo Dipartimento della relazione IMPIEGATI e la chiave Codice d e l l a r e l a z i o n e DIPARTIMENTI.

Questo è il motivo per cui, come vedremo nel Capitolo 4, nei sistemi relazionali è prevista una specifica più articolata per i vincoli di integrità referenziale.

2.3 Conclusioni Abbiamo visto in questo capitolo la definizione delle strutture e dei vincoli del modello relazionale. Abbiamo in primo luogo discusso il concetto di relazione, con gli adattamenti necessari per meglio sfruttare i concetti della teoria degli insiemi nel contesto delle basi di dati. Poi, abbiamo mostrato come le relazioni possano essere utilizzate per organizzare insiemi di dati anche complessi, utilizzando i dati stessi per realizzare riferimenti fra le diverse componenti (senza alcun utilizzo di puntatori espliciti). Quindi, dopo aver brevemente accennato alla necessità di utilizzare valori nulli per denotare l'assenza di informazioni, abbiamo discusso il concetto di vincolo di integrità, attraverso tre classi fondamentali: i vincoli di tupla, le chiavi e i vincoli di integrità referenziale. Nei prossimi capitoli completeremo la presentazione del modello relazionale da due punti di vista: • nel Capitolo 3 illustreremo i principi su cui si basano le operazioni di interrogazione di una base di dati;

• nel Capitolo 4 mostreremo come tutti i concetti, quelli relativi alle strutture e ai vincoli, discussi in questo capitolo, e quelli relativi alle operazioni (Capitolo 3), siano effettivamente realizzati nei DBMS reali, attraverso il linguaggio SQL, la cui presentazione sarà poi approfondita nei Capitoli 5 e 6.

Note bibliografiche Presentazioni del modello relazionale analoghe a quella di questo capitolo sono reperibili su tutti i moderni testi sulle basi di dati, a cominciare da quelli di Elmasri e Navathe [32], Silberschatz, Korth e Sudarshan [59] e Ramakhrishnan e Gehrke [54], nonché quello di Garcia-Molina, Ullman, e Widom [36]. Formalizzazioni ulteriori e approfondimenti teorici (molto più dettagliati di quelli che presenteremo nei prossimi capitoli) si trovano nei libri di teoria delle basi di dati, in italiano quello di Atzeni, Batini e De Antonellis [4] e in inglese quelli di Ullman [67], Maier [44], Atzeni e De Antonellis [6], Abiteboul, Hull e Vianu [1], Può essere interessante consultare l'articolo di Codd [24] che contiene la proposta originaria del modello, per constatarne tuttora l'attualità.

S o l u z i o n i sul sito

http: //www.ateneonline. it/atzeni

Esercizi2.1

Considerare le informazioni per la gestione dei prestiti di una biblioteca personale. Il proprietario presta libri ai propri amici, che indica semplicemente attraverso i rispettivi nomi o soprannomi (così da evitare omonimie) e fa riferimento ai libri attraverso i titoli (non possiede due libri con lo stesso titolo). Quando presta un libro, prende nota della data prevista di restituzione. Definire uno schema di relazione per rappresentare queste informazioni, individuando opportuni domini per i vari attributi e mostrarne un'istanza in forma tabellare. Indicare la chiave (o le chiavi) della relazione.

2.2

Rappresentare per mezzo di una o più relazioni le informazioni contenute nell'orario delle partenze da una stazione ferroviaria: numero, orario, destinazione finale, categoria, fermate intermedie, di tutti i treni in partenza.

2.3

Definire uno schema di base di dati per organizzare le informazioni di un'azienda che ha impiegati (ognuno con codice fiscale, cognome, nome e data di nascita), filiali (con codice, sede e direttore, che è un impiegato). Ogni impiegato lavora presso una filiale. Indicare le chiavi e i vincoli di integrità referenziale dello schema. Mostrare un'istanza della base di dati e verificare che soddisfi i vincoli.

2.4

Un albero genealogico rappresenta, in forma grafica, la struttura di una famiglia (o più famiglie, quando è ben articolato). Mostrare come si possa rappresentare, in una base di dati relazionale, un albero genealogico, cominciando eventualmente da una struttura semplificata, in cui si rappresentano solo le discendenze in linea maschile (cioè i figli vengono rappresentati solo per i componenti di sesso maschile) oppure solo quelle in linea femminile.

Cod.

Cognome

Nome

Paz.

Inizio

Fine

Rep.

A102 B372 B543 B444 S555

Necchi Rossini Missoni Missoni Rossetti

Luca Piero Nadia Luigi Gino

A102 A102 S555 B444 S555

2/05/94 2/12/94 5/10/94 1/12/94 5/10/94

9/05/94 2/01/95 3/12/94 2/01/95 1/11/94

A A B B A

MEDICI Matr.

Cogn.

Nome

Rep.

203 574 461 530 405 501

Neri Bisi Bargio Belli Mi zzi Monti

Piero Mario Sergio Nicola Nicola Mario

A B B C A A

REPARTI Cod.

Nome

Primario

A B C

Chirurgia Pediatria Medicina

203 574 530

Figura 2.23 Una base di dati per l'Esercizio 2.6 e 2.7

2.5

Per ciascuno degli Esercizi 2.1-2.4, valutare le eventuali esigenze di rappresentazione di valori nulli, con i benefici e le difficoltà connesse.

2.6

Descrivere in linguaggio naturale le informazioni organizzate nella base di dati in Figura 2.23.

2.7

Individuare le chiavi e i vincoli di integrità referenziale che sussistono nella base di dati di Figura 2.23 e che è ragionevole assumere siano soddisfatti da tutte le basi di dati sullo stesso schema. Individuare anche gli attributi sui quali possa essere sensato ammettere valori nulli.

2.8

Definire uno schema di base di dati che organizzi i dati necessari a generare la pagina dei programmi radiofonici di un quotidiano, con stazioni, ore e titoli dei programmi; per ogni stazione sono memorizzati, oltre al nome, anche la frequenza di trasmissione e la sede.

2.9

Indicare quali tra le seguenti affermazioni sono vere in una definizione rigorosa del modello relazionale: 1. 2. 3. 4. 5. 6. 7.

ogni relazione ha almeno una chiave; ogni relazione ha esattamente una chiave; ogni attributo appartiene al massimo a una chiave; possono esistere attributi che non appartengono a nessuna chiave; una chiave può essere sottoinsieme di un'altra chiave; può esistere una chiave che coinvolge tutti gli attributi; può succedere che esistano più chiavi e che una di esse coinvolga tutti gli attributi; 8. ogni relazione ha almeno una superchiave; 9. ogni relazione ha esattamente una superchiave; 10. può succedere che esistano più superchiavi e che una di esse coinvolga tutti gli attributi.

Matricola

Cognome

Nome

Età

101 102 103 104

Rossi Rossi Gialli Neri

Mario Anna Mario Gino

35 42 34 45

PROGETTI ID Titolo A B C

Luna Marte Giove

Costo 70 60 90

PARTECIPAZIONE Impiegato

Progetto

101 101 103 102

A B A B

Figura 2.24 Una base di dati per l'Esercizio 2.10

2.10 Considerare la base di dati relazionale in Figura 2.24, relativa a impiegati, progetti e partecipazioni di impiegati a progetti. Indicare quali possano essere, per questa base di dati, ragionevoli chiavi primarie e vincoli di integrità referenziale. Giustificare brevemente la risposta, con riferimento alla realtà di interesse (cioè perché si può immaginare che tali vincoli sussistano) e all'istanza mostrata (verificando che sono soddisfatti). 2.11 Si supponga di voler rappresentare in una base di dati relazionale le informazioni relative al calendario d'esami di una facoltà universitaria, che vengono pubblicate con avvisi con la struttura mostrata in Figura 2.25. Mostrare gli schemi delle relazioni da utilizzare (con attributi e vincoli di chiave e di integrità referenziale) e l'istanza corrispondente ai dati sopra mostrati. 2.12 Si considerino le seguenti relazioni utilizzate per tenere traccia degli studenti di un'università, dei loro esami superati e verbalizzati attraverso gli esoneri e dei loro esami superati e verbalizzati attraverso i comuni appelli.

C a l e n d a r i o esami Codice

Titolo

Prof

Appello

Data

1

Fisica

Neri

1 2 3 4

01/06/2006 05/07/2006 04/09/2006 30/09/2006

2

Chimica

Rossi

1 2

06/06/2006 05/07/2006

3

Algebra

Bruni

da definire

Figura 2.25 Un avviso con il calendario d'esami (Esercizio 2.11)

• ESAMIESONERI(Studente, Materia, VotoEsonl, VotoEson2, VotoFinale) . ESAMIAPPELLI(Studente, Materia, Voto) • STUDENTI(Matricola, Nome, Cognome) Indicare i vincoli di integrità che è ragionevole pensare debbano essere soddisfatti da tutte le basi di dati definite su questo schema.

Algebra e calcolo relazionale

Poiché le basi di dati vengono utilizzate per rappresentare le informazioni di interesse per applicazioni che gestiscono dati, è evidente che i linguaggi per la specifica delle operazioni (di interrogazione e aggiornamento) sui dati stessi costituiscono a loro volta una componente essenziale delle basi di dati e quindi di ciascun modello dei dati. Un aggiornamento può essere visto come una funzione che, data un'istanza di base di dati, produce un'altra istanza di base di dati, sullo stesso schema. Un'interrogazione, invece, è essenzialmente una funzione che, data un'istanza di base di dati, produce una relazione, su un dato schema. Quindi, esistono aspetti comuni a interrogazioni e aggiornamenti, che consistono nell'esigenza di esprimere funzioni definite sull'insieme delle istanze di una base di dati. In particolare, risulta utile studiare i fondamenti dei linguaggi di interrogazione, per poi vedere come i concetti stessi sono realizzati in pratica nei sistemi relazionali e introdurre infine le operazioni di aggiornamento, che mutuano alcuni concetti delle operazioni di interrogazione. Questo capitolo è appunto dedicato alla presentazione di linguaggi che, pur essendo diversi da quelli utilizzati dagli utenti nei sistemi, permettono però di esaminare varie questioni interessanti. In particolare, dedicheremo dapprima molto spazio all'algebra relazionale, un linguaggio procedurale (in cui cioè le operazioni complesse vengono specificate descrivendo il procedimento da seguire per ottenere la soluzione), illustrando i vari operatori, le espressioni e il modo in cui le espressioni possano essere trasformate per migliorarne l'efficienza. Accenneremo brevemente, sempre con riferimento all'algebra, a due argomenti: l'influenza che i valori nulli hanno sui linguaggi di interrogazione e le modalità secondo le quali possono essere definite relazioni virtuali (dette anche w'sfe), non memorizzate nella base di dati. Poi, presenteremo più sinteticamente il calcolo relazionale, che è viceversa un linguaggio dichiarativo, in cui le espressioni descrivono le proprietà del risultato, piuttosto che la procedura per ottenerlo. Questo linguaggio è basato sul calcolo dei predicati del primo ordine e ne presenteremo due versioni, la prima derivata direttamente dal calcolo dei predicati e la seconda che cerca di superare alcune limitazioni della prima. Concluderemo il capitolo con la breve trattazione del linguaggio Datalog, un interessante contributo della ricerca recente, che permette di formulare interrogazioni non esprimibili negli altri linguaggi. I paragrafi relativi al calcolo e al Datalog possono essere tralasciati senza alcun pregiudizio per la comprensione dei capitoli successivi del testo. Nel Capitolo 4, dedicato alI'SQL, vedremo come, dal punto di vista pratico, possa risultare utile combinare gli aspetti dichiarativi del calcolo e quelli procedurali dell'algebra. Vedremo anche come, in pratica, le operazioni di aggiornamento utilizzino gli stessi principi di quelle di interrogazione.

3.1

A l g e b r a relazionale

Come abbiamo detto, l'algebra relazionale è un linguaggio procedurale, basato su concetti di tipo algebrico. Sostanzialmente, esso è costituito da un insieme di operatori, definiti su relazioni e che producono ancora relazioni come risultati. In questo modo, è possibile costruire espressioni che coinvolgono più operatori, allo scopo di formulare interrogazioni anche complesse. Esaminiamo nei prossimi paragrafi i vari operatori: • prima quelli insiemistici tradizionali, unione, intersezione, differenza, che, con piccole avvertenze, possono essere definiti anche sulle relazioni; • poi quelli più specifici, ridenominazione, selezione, proiezione-, • infine il più importante, quello di join, in varie forme, join naturale, prodotto cartesiano e theta-join.

3.1.1 Unione, intersezione, differenza Per iniziare, notiamo che le relazioni sono insiemi, e quindi ha senso definire su di esse gli operatori insiemistici tradizionali di unione, differenza e intersezione (peraltro quest'ultima esprimibile per mezzo della differenza, in quanto è sempre vero che r fi s = r — (r — s)). Però, dobbiamo prestare attenzione al fatto che una relazione non è genericamente un insieme di tuple, ma un insieme di tuple omogenee, cioè definite sugli stessi attributi. Pertanto, pur potendo, in linea di principio, definire gli operatori in questione su qualunque coppia di relazioni, non ha senso, dal punto di vista del modello relazionale, definirli con riferimento a relazioni su attributi diversi. Per esempio, l'unione di due relazioni su schemi diversi sarebbe un insieme di tuple disomogenee, alcune definite sugli attributi della prima e le altre sugli altri. Ciò risulta insoddisfacente, perché un insieme di tuple disomogenee non è una relazione e noi, al fine di combinare gli operatori per formare espressioni complesse, vogliamo che i risultati siano relazioni. Pertanto, consideriamo ammissibili, nell'algebra relazionale, solo applicazioni degli operatori di unione, intersezione e differenza a coppie di operandi definite sugli stessi attributi. La Figura 3.1 mostra esempi di applicazioni dei tre operatori, che confermano le usuali definizioni, adattate al nostro contesto: • Vunione di due relazioni r\ e r2 definite sullo stesso insieme di attributi X è indicata con r\ U r2 ed è una relazione ancora su X contenente le tuple che appartengono a r\ oppure a r2, oppure a entrambe; • Vintersezione di n ( X ) e r2(X) è indicata con r\ H r2 ed è una relazione su X contenente le tuple che appartengono sia a n sia a r2\ • la differenza di r\{X) e r2(X) è indicata con r\ — r2 ed è una relazione su X contenente le tuple che appartengono a ri e non appartengono a r2.

Matricola

Cognome

Età

Matricola

Cognome

Età

7274 7432 9824

Rossi Neri Verdi

37 39 38

9297 7432 9824

Neri Neri Verdi

56 39 38

LAUREATI n DIRIGENTI

LAUREATI U DIRIGENTI Matricola

Cognome

Età

7274 7432 9824 9297

Rossi Neri Verdi Neri

37 39 38 56

LAUREATI -

Matricola

Cognome

Età

7432 9824

Neri Verdi

39 38

DIRIGENTI

Matricola

Cognome

Età

7274

Rossi

37

Figura 3.1 Operazioni di unione, intersezione e differenza

3.1.2 Ridenominazione La limitazione che abbiamo dovuto imporre agli operatori insiemistici, pur giustificata, risulta però particolarmente pesante. Consideriamo per esempio le due relazioni nella Figura 3.2: sarebbe sensato eseguire su di esse una sorta di unione, al fine di ottenere tutte le coppie "genitore-figlio" note alla base di dati, ma ciò non

MATERNITÀ

PATERNITÀ Padre

Figlio

Madre

Figlio

Adamo Adamo Abramo Abramo

Caino Abele Isacco Ismaele

Eva Eva Sara Agar

Caino Set Isacco Ismaele

PATERNITÀ U MATERNITÀ ?? Figura 3.2 U n ' u n i o n e sensata ma scorretta

Padre

Figlio

Genitore

Figlio

Adamo Adamo Abramo Isacco

Caino Abele Isacco Giacobbe

Adamo Adamo Abramo Isacco

Caino Abele Isacco Giacobbe

Figura 3.3 Una ridenominazione

è possibile, perché l'attributo che intuitivamente abbiamo indicato con Genitore si chiama in effetti Padre in una relazione e Madre nell'altra. Per risolvere il problema, introduciamo uno specifico operatore, che ha come unico obiettivo proprio quello di adeguare i nomi degli attributi, a seconda delle necessità, in particolare al fine di facilitare le operazioni insiemistiche. L'operatore è detto di ridenominazione, perché appunto "cambia il nome degli attributi", lasciando inalterato il contenuto delle relazioni. Consideriamo un esempio nella Figura 3.3: nella rappresentazione tabellare vediamo bene come, fra operando e risultato cambi solo l'intestazione, mentre il corpo rimane invariato. Infatti, la ridenominazione agisce solo sullo schema, nell'esempio cambiando il nome dell'attributo Padre in Genitore, come indicato dalla notazione Genitore , condizioni atomiche del tipo A6B o A6c, dove • 6 è un operatore di confronto ( = , ^ , > , < , > , Fi hanno l'usuale significato. Possiamo a questo punto completare la definizione: la selezione a f ir) produce una relazione sugli stessi attributi di r che contiene le tuple di r su cui F è vera.

3.1.4 Proiezione La definizione dell'operatore di proiezione è ancora più semplice: dati una relazione r(X) e un sottoinsieme Y di X, la proiezione di r su Y (indicata con JT YÌr))

Cognome

Nome

Reparto

Capo

Cognome

Nome

Rossi Neri Verdi Rossi

Mario Luca Mario Marco

Vendite Vendite Personale Personale

Gatti Gatti Lupi Lupi

Rossi Neri Verdi Rossi

Mario Luca Mario Marco

Figura 3.9 Una proiezione

è l'insieme di tuple su Y ottenute dalle tuple di r considerando solo i valori su Y\ JTY(r) = {t[Y]

| ter]

La Figura 3.9 mostra un primo esempio di proiezione, che illustra chiaramente il concetto già citato secondo il quale la proiezione permette di decomporre verticalmente le relazioni: il risultato della proiezione contiene in questo caso tante tuple quante l'operando, definite però solo su parte degli attributi. La Figura 3.10 mostra un'altra proiezione, in cui si nota una situazione diversa: il risultato contiene un numero di tuple inferiore rispetto a quelle dell'operando, perché alcune tuple, avendo uguali valori su tutti gli attributi della proiezione, danno lo stesso contributo alla proiezione stessa. Essendo le relazioni definite come insiemi, non possono in esse comparire più tuple uguali fra loro: i contributi uguali "collassano" in una sola tupla. In generale, possiamo dire che il risultato di una proiezione contiene al più tante tuple quante l'operando, ma può contenerne di meno, come mostrato nella Figura 3.10. Notiamo anche che esiste un legame fra i vincoli di chiave e le proiezioni, relativamente a questo problema: 71 y (r) contiene lo stesso numero di tuple di r se e solo se Y è superchiave per r. Infatti: • se Y è superchiave, allora r non contiene tuple uguali su Y, quindi ogni tupla dà un contributo diverso alla proiezione; • se la proiezione ha tante tuple quante l'operando, allora ciascuna tupla di r

IMPIEGATI

Cognome

Nome

Reparto

Capo

Rossi Neri Verdi Rossi

Mario Luca Mario Marco

Vendite Vendite Personale Personale

Gatti Gatti Lupi Lupi

^Reparto,capo (IMPIEGATI)

Reparto

Capo

Vendite Personale

Gatti Lupi

Figura 3.10 Una proiezione con m e n o t u p l e d e l l ' o p e r a n d o

contribuisce alla proiezione con valori diversi, quindi r non contiene coppie di tuple uguali su Y: ma questa è proprio la definizione di superchiave. Per la relazione IMPIEGATI nelle Figure 3.9 e 3.10, gli attributi Cognome e Nome formano una chiave (e perciò una superchiave), mentre Reparto e Capo non formano una superchiave: questo giustifica il comportamento riguardo al numero delle tuple. Come inciso, notiamo che una proiezione può produrre un numero di tuple pari a quelle dell'operando anche se gli attributi coinvolti non sono definiti come superchiave (nello schema). Per esempio, se riconsideriamo le relazioni discusse nel Capitolo 2 sullo schema S T U D E N T I ( Matricola,Cognome, Nome, Nascita, Corso)

possiamo dire che, per tutte le relazioni, la proiezione su Matricola e quella su Cognome, Nome e Nascita hanno lo stesso numero di tuple dell'operando. Al contrario, una proiezione su Cognome e Corso può avere meno tuple; però, nel caso particolare (come per esempio nella Figura 2.16) in cui non vi siano studenti diversi con lo stesso cognome iscritti allo stesso corso di laurea, allora anche la proiezione su Cognome e Corso ha lo stesso numero di tuple dell'operando. 3.1.5

Join

Passiamo ora a esaminare l'operatore di join' che è il più caratteristico dell'algebra relazionale, in quanto è l'operatore che permette di correlare dati contenuti in relazioni diverse, confrontando i valori contenuti in esse e utilizzando quindi la caratteristica fondamentale del modello, quella di essere basato su valori. Esistono, a parte alcune varianti, due versioni dell'operatore, comunque riconducibili l'una all'altra: la prima (il join naturale) utile per riflessioni di tipo astratto e la seconda (il theta-join) più rilevante dal punto di vista pratico. Join naturale II join naturale è un operatore (lo definiamo inizialmente in versione binaria, cioè con due operandi, per poi generalizzare) che correla dati in relazioni diverse, sulla base di valori uguali in attributi con lo stesso nome. Vediamo un esempio nella Figura 3.11, in cui l'operatore è denotato, come sarà sempre nel seguito, con il simbolo txl. Il risultato del join è costituito da una relazione sull'unione degli insiemi di attributi degli operandi e le sue tuple sono ottenute combinando le tuple degli operandi con valori uguali sugli attributi comuni (in questo caso l'attributo Reparto): per esempio, la prima tupla del join deriva dalla combinazione della prima tupla della relazione ri e della seconda tupla della relazione r2.

'Utilizziamo per questo operatore il termine in lingua inglese, perché in effetti la sua traduzione ("giunzione" o "congiunzione") non viene mai usata in questo contesto.

Impiegato

Reparto

Rossi Neri Bianchi

vendite produzione produzione

r\Wr2

r

2

Reparto produzione vendite

Impiegato

Reparto

Capo

Rossi Neri Bianchi

vendite produzione produzione

Bruni Mori Mori

Capo Mori Bruni

Figura 3.11 Un join naturale

In generale, il join naturale r\Wr2 di n ( X i ) e r2(X2) è una relazione definita su X\X2 (cioè sull'unione degli insiemi Xi e X2), come segue: ri M/*2 = { t su X\X2

|

esistono t\ e r\ e f 2 € r2 con t[X\] = 11 e f[X 2 ] = t2}

Più sinteticamente, ma in modo equivalente, possiamo scrivere: r

ìMr2 = {i su Xi X2

|

i[Xi] e n e t[X2]

e r2}

La definizione conferma che le tuple del risultato sono ottenute combinando tuple degli operandi con valori uguali sugli attributi comuni. Infatti, se indichiamo con X\ 2 gli attributi comuni (cioè X\ 2 = Xi fi X2), le due condizioni ?[A"i] = t\ e t[X2] = t2 implicano (poiché X\2 c e Xl2 c X2 ) che r[X| 2 ] = ii[Xi. 2 ] e t[Xi.2] = h[Xij], quindi ii[X I 2 ] = t2[X\2~\. Il grado della relazione ottenuta come risultato di un join è minore o uguale della somma dei gradi dei due operandi, perché gli attributi omonimi degli operandi compaiono una sola volta nel risultato. E opportuno notare che è molto frequente eseguire join sulla base di valori della chiave di una delle relazioni coinvolte, esplicitando i riferimenti fra tuple che, come abbiamo più volte ripetuto, sono realizzati per mezzo di valori, soprattutto valori di chiavi. In molti di questi casi, è anche definito, fra gli attributi coinvolti, un vincolo di integrità referenziale. Riconsideriamo per esempio le relazioni INFRAZIONI e AUTO nella base di dati nella Figura 2.19, ripetute per comodità nella Figura 3.12 insieme al join di esse. Notiamo che ciascuna delle tuple di INFRAZIONI è stata combinata con una e una sola delle tuple di AUTO: (i) una sola perché Prov e Numero formano una chiave di AUTO (ii) almeno una perché è definito il vincolo di integrità referenziale fra Prov e Numero in INFRAZIONI e (la chiave primaria di) AUTO. 11 join, quindi, ha esattamente tante tuple quante la r e l a z i o n e INFRAZIONI.

INFRAZIONI

AUTO

Codice

Data

Ag

Art

Prov

Numero

143256 987554 987557 630876 539856

25/10/08 26/IO/OS 26/10/08 15/10/08 12/10/08

567 456 456 456 567

44 34 34 53 44

RM RM RM MI MI

4E5432 4E5432 2F7643 2F7643 2F7643

Prov

Numero

RM RM RM MI

2F7643 1A2396 4E5432 2F7643

Proprietario Verdi Verdi Bini Luci

Piero Piero Luca Gino

Indirizzo Via Via Via Via

Tigli Tigli Aceri Aceri

INFRAZIONI XI AUTO Codice

Data

Ag

Art

Prov

Numero

143256 987554 987557 630876 539856

25/10/08 26/10/08 26/10/08 15/10/08 12/10/08

567 456 456 456 567

44 34 34 53 44

RM RM RM MI MI

4E5432 4E5432 2F7643 2F7643 2F7643

Proprietario Bini Bini Verdi Luci Luci

Luca Luca Piero Gino Gino

Indirizzo Via Via Via Via Via

Aceri Aceri Tigli Aceri Aceri

Figura 3.12 Le relazioni INFRAZIONI e AUTO e il loro join

La Figura 3.13 mostra un altro esempio di join, sulle stesse relazioni riguardo alle quali abbiamo già visto (Figura 3.4) una unione preceduta da ridenominazione: qui combiniamo i dati nelle due relazioni sulla base del valore del figlio, ottenendo la coppia di genitori, per ogni persona per cui entrambi siano indicati nella base di dati. I due esempi considerati insieme ci mostrano quindi come i vari operatori dell'algebra relazionale permettano di combinare e correlare in vario modo, a seconda delle necessità, i dati contenuti in una base di dati. Join completi e incompleti Discutiamo ora diversi esempi di join, per svolgere alcune importanti considerazioni, con riferimento alla dimensione del risultato e al contributo a esso portato dalle tuple degli operandi. Nell'esempio nella Figura 3.11, possiamo dire che ciascuna tupla di ciascuno degli operandi contribuisce ad almeno una tupla del risultato (il join si dice in questo caso completo)-. per ogni tupla ri di ri, esiste una tupla t in riXr 2 tale che / [ X | ] = t\ (e analogamente per r 2 ). Questa proprietà non è sempre verificata, perché richiede una corrispondenza fra le tuple delle due relazioni. La Figura 3.14 mostra un join in cui alcune tuple degli operandi (in particolare la prima di r, e la seconda di r 2 ) non contribuiscono al risultato, perché l'altra relazione non contiene tuple con gli

Padre

Figlio

Adamo Adamo Abramo Abramo

Caino Abele Isacco Ismaele

MATERNITÀ

Madre

Figlio

Eva Eva Sara Agar

Caino Set Isacco Ismaele

PATERNITÀMMATERNITÀ Padre

Figlio

Madre

Adamo Abramo Abramo

Caino Isacco Ismaele

Eva Sara Agar

Figura 3.13 Figli con entrambi i genitori

stessi valori sull'attributo comune. In inglese tali tuple vengono chiamate dangling (cioè "dondolanti").l'EspressTuplaldangling Come caso limite, è ovviamente possibile che nessuna delle tuple degli operandi sia combinabile, e allora il risultato del join è la relazione vuota (Figura 3.15). All'estremo opposto, è possibile che ciascuna delle tuple di ciascuno degli operandi sia combinabile con tutte le tuple dell'altro, come mostrato nella Figura 3.16. In tal caso, il risultato contiene un numero di tuple pari al prodotto delle cardinalità degli operandi e cioè | n | x |r 2 | tuple (dove |r| indica la cardinalità della relazione r). Ricapitolando, possiamo dire che il join di ri e r2 contiene un numero di tuple compreso fra 0 e |/-j | x \r2\. Inoltre: • se il join di r\ e r2 è completo, allora contiene almeno un numero di tuple pari al massimo fra |ri | e \r2\\

r1

Impiegato

Reparto

Rossi Neri Bianchi

vendite produzione produzione

r\Wr2

n

Reparto

Capo

produzione acquisti

Mori Bruni

Impiegato

Reparto

Capo

Neri Bianchi

produzione produzione

Mori Mori

Figura 3.14 Un join con t u p l e

dangling

Impiegato

Reparto

Rossi Neri Bianchi

vendite produzione produzione Impiegato

>'2 Reparto

Capo

concorsi acquisti

Mori Bruni

Reparto

Capo

Figura 3.15 Un join v u o t o

• se Xi fi X2 contiene una chiave per r2, allora il join di ri (X] ) e riiXj) contiene al più | n | tuple; • se Xi fi X2 coincide con una chiave per r2 e sussiste il vincolo di riferimento fra Xi fi X2 in r\ e la chiave di r2, allora il join di r i ( X i ) e r2(X2) contiene esattamente | n | tuple. Join esterni La caratteristica dell'operatore di join di "tralasciare" le tuple di una relazione senza controparte nell'altra è utile in molti casi ma potenzialmente pericolosa in altri, in quanto può portare a omettere informazioni rilevanti. Consideriamo per esempio il join in Figura 3.14, supponendo di essere interessati a tutti gli impiegati, con l'indicazione del capo se noto. Allo scopo, è stata proposta (e recepita nelle ultime versioni dell'SQL, e la approfondiremo quindi nel Paragrafo 4.3.2) una variante dell'operatore di join chiamata join esterno (in inglese outer join), che prevede che tutte le tuple diano un contributo al risultato, eventual-

n

Impiegato

Progetto

Rossi Neri Bianchi

A A A

r\Wr 2

Progetto

Capo

A A

Mori Bruni

Impiegato

Reparto

Capo

Rossi Neri Bianchi Rossi Neri Bianchi

A A A A A A

Mori Mori Mori Bruni Bruni Bruni

Figura 3.16 U n join con |n| x \r2\ tuple

Impiegato

Reparto

Rossi Neri Bianchi

vendite produzione produzione

'I^LEFT'l

'"l^RIGHT^

''I^FULL^

Reparto

Capo

produzione acquisti

Mori Bruni

Impiegato

Reparto

Capo

Rossi Neri Bianchi

vendite produzione produzione

NULL Mori Mori

Impiegato

Reparto

Capo

Neri Bianchi NULL

produzione produzione acquisti

Mori Mori Bruni

Impiegato

Reparto

Capo

Rossi Neri Bianchi NULL

vendite produzione produzione acquisti

NULL Mori Mori Bruni

Figura 3.17 Alcuni join esterni

mente estese con valori nulli ove non vi siano controparti opportune. Esistono tre varianti per l'operatore: il join esterno sinistro, che estende solo le tuple del primo operando, quello destro, che estende solo le tuple del secondo operando, e quello completo, che le estende tutte. Mostriamo in Figura 3.17 esempi di join esterno sulle relazioni già mostrate nella Figura 3.14, con una sintassi autoesplicativa. Join n-ario, intersezione e prodotto cartesiano Vediamo alcune proprietà dell'operatore di join naturale. 2 In primo luogo, osserviamo che esso è commutativo, poiché riMA*2 è sempre uguale a r 2 Xri, e associativo, in quanto n M ^ N r i ) è uguale a (A*itxir2)Mr3. Pertanto, potremo scrivere, ove necessario, sequenze di join senza parentesi: ritXr 2 txl... Xr„ oppure txlJLj/", Notiamo poi che non abbiamo fatto alcuna ipotesi specifica sugli insiemi di attributi Xj e X2 su cui sono definiti gli operandi. Di conseguenza, ha senso consider i riferiamo qui al join naturale come tale, non al join esterno, perii quale alcune delle proprietà non valgono.

rare anche i casi estremi, quello in cui sono uguali e quello in cui sono disgiunti. In entrambi i casi, si applica la definizione generale vista sopra, ma è opportuno fare alcune osservazioni. Se = X2, allora il join coincide in effetti con l'intersezione: rx{X{)Mr2(XÙ =n(Xi)nr2(Xi) in quanto, nella definizione, si richiede che il risultato sia definito sull'unione dei due insiemi di attributi, e che contenga le tuple t tali che r[Xj ] e rx e f[X 2 ] e r 2 ; se X\ = X2, allora l'unione di X\ e X2 è ancora pari a Xi, quindi t è definita su X\ \ la definizione richiede pertanto che t e n e t e r2 e coincide perciò con la definizione di intersezione. Il caso in cui i due insiemi di attributi sono disgiunti merita ancor maggiore attenzione. Il risultato è sempre definito sull'unione X i X 2 ) e ciascuna tupla deriva sempre da due tuple, una per ciascuno degli operandi, ma, in effetti, poiché tali tuple non hanno attributi in comune, non viene richiesta a esse nessuna condizione per partecipare insieme al join: la condizione che informalmente abbiamo prima discusso, e cioè che le due tuple devono avere gli stessi valori sugli attributi comuni, degenera in una condizione sempre verificata. Quindi, il risultato del join contiene le tuple ottenute combinando, in tutti i modi possibili, le tuple degli operandi. In questo caso particolare, si dice spesso che il join diventa un prodotto cartesiano. Potremmo dire che il prodotto cartesiano è un operatore definito (con la stessa definizione data sopra per il join naturale) su relazioni che non hanno attributi in comune. L'uso del termine è in effetti improprio, in quanto non si tratta di un prodotto cartesiano fra insiemi: il prodotto cartesiano di due insiemi è un insieme di coppie (con il primo elemento dal primo insieme e il secondo dal secondo), mentre qui abbiamo tuple, ottenute concatenando tuple della prima relazione e tuple della seconda. La Figura 3.18 mostra un esempio di prodotto cartesiano, confermando come il risultato contenga un numero di tuple pari al prodotto delle cardinalità degli operandi. Theta-join ed equi-join Osservando la Figura 3.18 possiamo anche notare che un prodotto cartesiano ha di solito ben poca utilità, in quanto concatena tuple non necessariamente correlate dal punto di vista semantico. In effetti, il prodotto cartesiano viene spesso seguito da una selezione, che centra l'attenzione su tuple correlate secondo le esigenze. Per esempio, sulle relazioni IMPIEGATI e PROGETTI ha senso definire un prodotto cartesiano seguito dalla selezione che mantiene solo le tuple con valori uguali sull'attributo Progetto di IMPIEGATI e su Codice di PROGETTI (Figura 3.19). Per questa ragione, viene spesso definito un operatore derivato (cioè esprimibile per mezzo di altri operatori), il theta-join, come prodotto cartesiano seguito da una selezione, nel modo seguente (dove F è una formula proposizionale utilizzabile in una selezione e le relazioni r\ e r2 non hanno attributi in comune): rxwFr2

= o f (/"i Mr2 )

La relazione nella Figura 3.19 può quindi essere ottenuta per mezzo del theta-join:

PROGETTI

Impiegato

Progetto

Rossi Neri Neri

A A B

Codice

Nome

A B

Venere Marte

IMPIEGATI M PROGETTI

Impiegato

Progetto

Codice

Nome

Rossi Neri Neri Rossi Neri Neri

A A B A A B

A A A B B B

Venere Venere Venere Marte Marte Marte

Figura 3.18 Un prodotto cartesiano

IMPIEGATI N P r o g e „ o = c o d i c e P R O G E T T I

Un theta-join in cui la condizione di selezione F sia una congiunzione di atomi di uguaglianza, con un attributo della prima relazione e uno della seconda, viene chiamato equi-join. Quindi la relazione nella Figura 3.19 è ottenuta per mezzo di un equi-join. Dal punto di vista pratico il theta-join e ancor più l'equi-join hanno una grande importanza, in quanto la maggior parte dei sistemi di basi di dati effettivamente

IMPIEGATI

PROGETTI

Impiegato

Progetto

Rossi Neri Neri

A A B

Codice

Nome

A B

Venere Marte

& Progetto=Codice(IMPIEGATI M PROGETTI)

Impiegato

Progetto

Codice

Nome

Rossi Neri Neri

A A B

A A B

Venere Venere Marte

Figura 3.19 Un prodotto cartesiano seguito da una selezione

esistenti non utilizzano i nomi di attributo per correlare relazioni, e pertanto non utilizzano il join naturale ma l'equi-join e il theta-join. Approfondiremo questa osservazione quando discuteremo la specifica delle interrogazioni nel linguaggio SQL nel Capitolo 4. Peraltro, sottolineiamo che il join naturale, reso disponibile in pratica solo nelle ultime versioni dell'SQL, permette di elaborare in modo semplice riflessioni che sono poi estendibili all'equi-join. Notiamo tra l'altro come il join naturale possa essere simulato per mezzo della ridenominazione, dell'equijoin e della proiezione. Senza scendere nel dettaglio, mostriamo un esempio. Date due relazioni n(ABC) e r2{BCD), il join naturale di r\ e r2 può essere espresso per mezzo degli altri operatori, in tre passi: . ridenominando gli attributi in modo di ottenere relazioni su schemi disgiunti: • effettuando l'equi-join, con condizioni di uguaglianza sugli attributi corrispondenti: r 1 MB = B ' A c=c'PB'c'^-Bc( r 2); • concludendo con una proiezione che elimina gli attributi "doppioni," che presentano valori identici a quelli di altri attributi: ABC D(f\^B=B'

AC=C'

P B'C +-Bc(r2))

3.1.6 Interrogazioni in algebra relazionale In generale, un'interrogazione può essere definita come una funzione che, applicata a istanze di basi di dati, produce relazioni. Più precisamente, dato uno schema R di base di dati, un'interrogazione è una funzione che, per ogni istanza r di R, produce una relazione su un dato insieme di attributi X. Le espressioni dei vari linguaggi di interrogazione (per esempio dell'algebra relazionale) "rappresentano" o "realizzano" interrogazioni: ogni espressione definisce una funzione. Indichiamo con E(r) il risultato dell'applicazione dell'espressione E alla base di dati r. In algebra relazionale, le interrogazioni su uno schema di base di dati R vengono formulate con espressioni i cui atomi sono (nomi di) relazioni in R (le "variabili"). Concludiamo la presentazione dell'algebra relazionale mostrando la formulazione di alcune interrogazioni di crescente complessità, che fanno riferimento allo schema contenente le due relazioni: l M P l E G A T l ( M a t r , N o m e , Età, Stipendio) SuPERVisiQNE(Capo,lmpiegato)

Una base di dati su tale schema è mostrata nella Figura 3.20. La prima interrogazione che consideriamo è molto semplice, in quanto coinvolge una sola relazione: trovare matricola, nome ed età degli impiegati che guadagnano più di 40 mila euro. In questo caso, con una selezione possiamo porre l'attenzione sulle sole tuple che soddisfano la condizione (stipendio maggiore di 40 mila euro) e con una proiezione eliminiamo gli attributi non richiesti: TC Matr. Nome. Età

Stipendio>4o( IM PIEGATI))

(3.1)

Matr

Nome

Età

Stipendio

101 103 104 105 210 231 252 301 375

Mario Rossi Mario Bianchi Luigi Ned Nico Bini Marco Celli Siro Bisi Nico Bini Sergio Rossi Mario Rossi

34 23 38 44 49 50 44 34 50

40 35 61 38 60 60 70 70 65

SUPERVISIONE

Capo

Impiegato

210 210 210 231 301 301 375

101 103 104 105 210 231 252

Figura 3.20 Una base di dati per gli esempi di espressioni

Il risultato di questa espressione, applicata alla base di dati nella Figura 3.20, è mostrato nella Figura 3.21. La seconda interrogazione coinvolge entrambe le relazioni, in modo molto naturale, trovare le matricole dei capi degli impiegati che guadagnano più di 40 mila euro: 7Tcapo(SUPERVISIONEXl|mpiegato=Matr 4o(lMPIEGATl))

Matr

Nome

Età

104 210 231 252 301 375

Luigi Neri Marco Celli Siro Bisi Nico Bini Sergio Rossi Mario Rossi

38 49 50 44 34 50

(3.2)

Capo 210 301 375 Figura 3.22 II risultato dell'applicazione dell'Espressione 3.2 alla base di dati nella Figura 3.20

Nella Figura 3.22 è mostrato il risultato, sempre con riferimento alla base di dati nella Figura 3.20. Passiamo a esempi un po' più complessi, in cui il coinvolgimento delle due relazioni è più articolato. Cominciamo aggiungendo solo un piccolo elemento all'interrogazione precedente: trovare nome e stipendio dei capi degli impiegati che guadagnano più di 40 mila euro. In questo caso, possiamo ovviamente far uso dell'espressione precedente, ma dobbiamo poi produrre, per ciascuna tupla del risultato, le informazioni richieste sul capo, che vanno estratte dalla relazione IMP I E G A T I . È evidente, quindi, che ogni tupla del risultato è costruita a partire da tre rupie, la prima di IMPIEGATI, relativa a un impiegato che guadagna più di 40 mila euro, la seconda di SUPERVISIONE, che indica la matricola del capo dell'impiegato in questione, e la terza di nuovo di IMPIEGATI, con le informazioni relative al capo. Intuitivamente, la soluzione prevede il join della relazione IMPIEGATI con il risultato dell'espressione precedente, ma con una avvertenza: in generale, il capo e l'impiegato differiscono, quindi le due tuple di IMPIEGATI che contribuiscono a una tupla del join sono diverse. Il join deve quindi essere preceduto da una ridenominazione che "cambi" tutti i nomi degli attributi. Una possibile espressione allo scopo è la seguente (in cui alcuni nomi di attributo sono stati abbreviati per ragioni di spazio): NomeC, StipC ( P M a t r C , N o m e C . S t i p C . E t à C < - M a t r , Nome. Stip. Età ( I M P I E G A T I ) ^MatrC=Capo

SUPERVISIONEM| m p = M a t r

CTStip>4o(lMPIEGATl))

(3.3)

Nella Figura 3.23 è mostrato il risultato, sempre con riferimento alla base di dati nella Figura 3.20.

NomeC

StipC

Marco Celli Sergio Rossi Mario Rossi

60 70 65

Matr

Nome

Stip

MatrC

NomeC

StipC

104 252

Luigi Neri Nico Bini

61 70

210 375

Marco Celli Mario Rossi

60 65

Figura 3.24 II risultato dell'applicazione dell'Espressione 3.4 alla base di dati nella Figura 3.20

Il prossimo esempio è una variante del precedente, in quanto richiede il confronto di due valori dello stesso attributo, di tuple diverse: trovare gli impiegati che guadagnano più del rispettivo capo, mostrando matricola, nome e stipendio di ciascuno di essi e del capo. L'espressione è simile a quella precedente, e si nota ancora di più la necessità delle ridenominazioni (il risultato è nella Figura 3.24): H

Matr.Nome.Stip.MatrC.NomeC.StipC

(°rStip>Stipc(PMatrC.NomeC.StipC.EtàCO(R))

= O A>O(X

AB(R))

mentre la seguente equivalenza: 7 T . 4 B ( f l , ) w r a c ( R 2 ) =R

7Tabc(R^R2)

sussiste se e solo se nello schema R l'intersezione fra gli insiemi di attributi di R\ e R2 è pari ad A. Infatti, se ci fossero anche altri attributi, il join opererebbe solo su A nella prima espressione e su A e tali altri attributi nella seconda, con risultati in generale diversi. L'equivalenza di espressioni dell'algebra risulta particolarmente importante dal punto di vista applicativo, nella fase di esecuzione delle interrogazioni. Infatti, le interrogazioni, specificate in linguaggio SQL (Capitolo 4), vengono tradotte in algebra relazionale e, appunto con riferimento all'algebra, viene valutato il costo, sostanzialmente in termini di dimensioni dei risultati intermedi. In presenza di varie alternative equivalenti, viene scelta quella con costo minore. In questo contesto, vengono spesso utilizzate trasformazioni di equivalenza, cioè operazioni che sostituiscono un'espressione con un'altra a essa equivalente. In particolare, risultano interessanti le trasformazioni che riducono le dimensioni dei risultati intermedi e quelle che preparano un'espressione all'applicazione di una trasformazione che riduce le dimensioni dei risultati intermedi. Vediamo un primo insieme di trasformazioni interessanti. 1. Atomizzazione delle selezioni: una selezione congiuntiva può essere sostituita da una cascata di selezioni atomiche: aFi^F2(E)

= ff/r, (cr

Fi{E))

dove E è una qualunque espressione. Questa trasformazione permette di applicare successive trasformazioni che operano su selezioni con condizioni atomiche. 2. Idempotenza delle proiezioni: una proiezione può essere trasformata in una cascata di proiezioni che "eliminano" i vari attributi in fasi diverse: 7TX(E)

=

7TX(7TXY(E))

se E è definita su un insieme di attributi che contiene Y (oltre a X). Anche questa è una trasformazione preliminare ad altre. 3. Anticipazione della selezione rispetto al join (descritta spesso in inglese con pushing selections down): a F(ElME2)

=

E[MGf(E2)

se la condizione E fa riferimento solo ad attributi nella sottoespressione E2. 4. Anticipazione della proiezione rispetto al join (pushing projections down): siano E\ ed E2 definite rispettivamente su I ] e X 2 ; se ^ Q X2 e Y2 D (Xj fi X2) (cioè gli attributi in X2 — Y2 non sono coinvolti nel join) allora vale l'equivalenza: 7TXiy2(E^E2)

=

E^7Ty2(E2)

Combinando questa regola con quella della idempotenza delle proiezioni, possiamo ottenere la seguente equivalenza: 7TY(E\MfE2)

= 7T y(7T YtiE^F-TT

Yl(E2))

dove, indicando con X\ e X2 gli attributi di E\ ed E2 rispettivamente e con J\ e J2 i rispettivi sottoinsiemi coinvolti nella condizione F di join: n = ( X , n Y) u jx Y2 = (X2

DY)UJ2

In sostanza, possiamo eliminare subito da ciascuna relazione gli attributi che non compaiono nel risultato finale e non sono coinvolti nel join. 5. Inglobamento di una selezione in un prodotto cartesiano a formare un join: CTf(EiNE2)

=

ElMFE2

con E\ D E2 = 0. Vediamo un esempio che chiarisce l'uso delle trasformazioni preparatorie e l'importante regola di anticipazione delle selezioni. Supponiamo di voler trovare, con riferimento alla base di dati di Figura 3.20, i numeri di matricola dei capi di impiegati con meno di trenta anni. Una prima espressione utile allo scopo potrebbe specificare il prodotto cartesiano delle due relazioni seguito da una selezione congiuntiva e poi da una proiezione: ^Capo(O- M atr=lmpAEtà30(PERSONE)

restituisce le persone la cui età è nota e maggiore di 30, mentre per ottenere quelle che hanno o potrebbero avere più di trent'anni (cioè quelle per cui l'età è nota e maggiore di 30 oppure non nota), possiamo utilizzare l'espressione: ® Età>30vEt i s N U L L ( P E R S O N E )

Analogamente, le espressioni OrEtà>30(PERSONE) U

CTETÀ30VETÀ 4 0 ) ) ) ) }

(3.13)

Questa espressione seleziona un capo c se, per ogni quadrupla di valori m', n , e', s' relativi a impiegati di c, si ha che s' è maggiore di 40. La struttura corrisponde alla condizione "se / allora g" (nel nostro caso, "se m'è un impiegato avente c come capo, allora lo stipendio di m! è maggiore di 40"), in quanto è vera in tutti i casi escluso quello in cui / è vera e g è falsa.

Vale la p e n a di n o t a r e c h e le leggi di d e M o r g a n c h e v a l g o n o p e r gli o p e r a t o r i d e l l ' a l g e b r a di B o o l e , in m o d o che:

-(/

A

g) =

- ( / ) V

-i(g)

^ ( f v g )= -(/) valgono, mutatis mutandis, anche per i quantificatori: 3 x { f ) = -(V.rM/))) W x ( f ) = -(3JC ( - ( / ) ) ) In effetti, le due formulazioni che abbiamo mostrato per l'ultima interrogazione possono essere ottenute l'una dall'altra per mezzo di queste equivalenze. Più in generale, possiamo trarre anche la conseguenza che è possibile usare una forma ridotta del calcolo (ma senza perdita di potere espressivo), in cui compaiono la negazione, un solo connettivo (per esempio la congiunzione) e un solo quantificatore (per esempio l'esistenziale, che è di più naturale comprensione).

3.2.2 Pregi e difetti del calcolo su domini Il calcolo relazionale presenta, come dimostrato dagli esempi, aspetti interessanti, soprattutto per la dichiaratività, ma anche alcuni difetti e limitazioni, che è opportuno discutere, per arrivare a versioni più interessanti e, soprattutto, significative dal punto di vista pratico. In primo luogo, notiamo che il calcolo ammette espressioni che hanno veramente poco senso, almeno dal punto di vista pratico. Per esempio, l'espressione: {A, : xi,

A2 : x2 \ R(A{

: xi) AX2

= x2)

produce come risultato una relazione su 40}

(3.16)

Notiamo come la formula preveda la congiunzione di due condizioni atomiche, una che corrisponde alla condizione di join (/.Matr = s.lmpiegato) e l'altra alla solita condizione di selezione (/.Stipendio > 40). Nel caso delle espressioni corrispondenti al join di una relazione con se stessa, abbiamo più variabili aventi la stessa relazione come range. L'interrogazione: trovare nome e stipendio dei capi degli impiegati che guadagnano più di 40 mila euro (Espressioni 3.3 e 3.10), può essere realizzata con l'espressione: {NomeC, StipC : /'.(Nome, Stip) | /'(IMPIEGATI),

/'.Matr =

J(SUPERVISIONE),

/(IMPIEGATI)

|

Capo A S.Impiegato = /.Matr A /.Stipendio > 40} (3.17)

In modo analogo troviamo anche gli impiegati che guadagnano più del rispettivo capo, mostrando matricola, nome e stipendio di ciascuno di essi e del capo, (3.4 in algebra e 3.11 in calcolo su domini): {/.(Nome. Matr, Stip), NomeC. MatrC, StipC : /'.(Nome, Matr, Stip) | /(IMPIEGATI),

S(SUPERVISIONE),

/'(IMPIEGATI)

|

/.Matr = ^.Impiegato A .V.Capo = /'.Matr A/.Stipendio > /'.Stipendio}(3.18) Le interrogazioni con i quantificatori mostrano appieno la maggiore sinteticità e praticità del calcolo su tuple con dicharazioni di range. L'interrogazione che richiede di trovare matricola e nome dei capi i cui impiegati guadagnano tutti più di 40 mila euro (Espressione 3.5 in algebra ed Espressione 3.12 o 3.13 in calcolo

s u d o m i n i ) si e s p r i m e c o n u n n u m e r o a s s a i i n f e r i o r e di q u a n t i f i c a t o r i e v a r i a b i l i . A b b i a m o di n u o v o v a r i e a l t e r n a t i v e , s u l l a b a s e d e l l ' u s o dei d u e q u a n t i f i c a t o r i e della negazione. C o n quantificatori universali:

{/.(Matr. Nome) | /.Matr = J.Capo

¿(IMPIEGATI), ^(SUPERVISIONE)

|

A V/'(1MPIEGATI)(W(SUPERVISIONE)

(-•(i.Capo = s'.Capo A S'.Impiegato = / .Matr) v /'.Stipendio > 40))}(3.19) Con quantificatori esistenziali negati: {/.(Matr, Nome) |

/'.Matr = I.Capo

/(IMPIEGATI), S(SUPERVISIONE)

|

A ->(3I'(IMPIEGATI)(3Ì'(SUPERVISIONE)

(í.Capo = s'.Capo A S'.Impiegato = /".Matr A /".Stipendio < 40)))} (3.20) Purtroppo, il calcolo su tupie con dichiarazioni di range non permette di esprimere tutte le interrogazioni che possono essere formulate in algebra relazionale (o, equivalentemente, nel calcolo su domini). In particolare, le interrogazioni i cui risultati possono provenire indifferentemente da due o più relazioni (che in algebra realizziamo con l'operatore di unione) non possono essere espresse in questa versione del calcolo: infatti, i risultati sono costruiti a partire da tutte le variabili libere, i cui range sono definiti nella target list, e ogni variabile ha come range una sola relazione. Consideriamo per esempio la semplice unione di due relazioni sugli stessi attributi: date R\(AB) e RIIAB), vogliamo formulare l'interrogazione che in algebra esprimeremmo con l'unione di R\ e RJ. Se l'espressione avesse due variabili libere, allora ogni tupia del risultato dovrebbe corrispondere a una tupia di ciascuna delle relazioni, il che non è necessario, perché l'unione richiede alle tupie nel risultato di comparire in almeno uno degli operandi, non necessariamente in entrambi. Se viceversa l'espressione avesse una sola variabile libera, questa dovrebbe far riferimento a una sola delle relazioni, senza acquisire tupie dall'altra per il risultato. Per questo motivo, SQL, il linguaggio pratico effettivamente utilizzato per l'interrogazione di basi di dati, che vedremo in dettaglio nel Capitolo 4, e che è basato sul calcolo su tupie con dichiarazioni di range, prevede un costrutto esplicito di unione, per esprimere interrogazioni che altrimenti risulterebbero non esprimibili. Notiamo che se permettessimo di associare a una variabile un range costituito da più relazioni, risolveremmo il problema della semplice unione di due relazioni, ma non riusciremmo comunque a formulare unioni complesse i cui operandi siano sottoespressioni non direttamente corrispondenti a schemi di relazioni. Per esempio, date due relazioni RI(ABC) e RZ(BCD), l'unione delle loro proiezioni su BC:

JT bc(R\)D7T

bc^RI)

non potrebbe essere espressa, perché le due relazioni hanno schemi diversi, quindi non può una sola variabile essere associata a entrambe.

Sottolineiamo che, mentre l'operatore di unione non è esprimibile in questa versione del calcolo relazionale, gli operatori di intersezione e differenza risultano esprimibili.

, L'intersezione richiede che le tuple del risultato appartengano a entrambi gli operandi, quindi si può costruire il risultato a partire da una relazione, richiedendo l'esistenza di una tupla uguale nell'altra relazione; per esempio, l'intersezione: TCBc(R\)n7TBc(R2) può essere espressa con:

{x\.BC | xi(Ri)

| 3x2(R2)(xi.B

= x2.B AxuC

= x2.C)}

• In modo simile, la differenza, che produce le tuple di un operando non contenute nell'altro, può essere specificata richiedendo appunto le tuple del minuendo che non compaiono nel sottraendo; per esempio: 7Tbc(R\)

~

7tBC(R2)

può essere espressa con: {xi.BC

|

XI(RÌ)

| - 4 0

(3.21)

Per valutare un'interrogazione come questa (come qualunque interrogazione che coinvolga predicati intensionali), è necessario definire la semantica delle regole.

L ' i d e a di base è che il corpo di una regola va considerato come la congiunzione degli atomi che in esso compaiono, quindi la regola può essere valutata come un'espressione del calcolo su domini (in cui appunto il corpo, sostituendo le virgole con and, diventa la formula, e la testa, a parte il nome del predicato intensionale, la target list). L a regola 3 . 2 1 definisce la relazione intensionale C A P I D E I R I C C H I c o m e costituita dalle stesse tuple che compaiono nel risultato dell'Espressione 3.9 del calcolo, che ha appunto la struttura sopra citata: {Capo : c

| l M P i E G A T i ( M a t r : m,

N o m e : n,

Età : e, S t i p e n d i o : s) A

S u P E R V i s i o N E ( l m p i e g a t o : m, C a p o : C) A S > 40}

In modo analogo possiamo scrivere regole (con predicati intensionali ausiliari) per molte delle interrogazioni che abbiamo visto nei paragrafi precedenti. In assenza di definizioni ricorsive, la semantica del Datalog è quindi molto semplice, nel senso che i vari predicati intensionali possono essere calcolati per mezzo di espressioni simili a quelle del calcolo. In effetti, con la definizione finora illustrata per il Datalog, non è possibile formulare tutte le interrogazioni esprimibili nel calcolo (e nell'algebra), perché non è disponibile un costrutto che corrisponda al quantificatore universale (o alla negazione nel senso pieno del termine). In effetti, si può dimostrare che: • il Datalog non ricorsivo è equivalente al calcolo su domini senza negazione né quantificazione universale. 5 Per far acquisire al Datalog lo stesso potere espressivo del calcolo è necessario aggiungere alla struttura base la possibilità di includere nel corpo, non solo condizioni atomiche, ma anche negazioni di condizioni atomiche (che indicheremo con il simbolo NOT). Solo in questo modo è possibile esprimere l'interrogazione che richiede di trovare matricola e nome dei capi i cui impiegati guadagnano tutti più di 40 mila euro. Espressione 3.12: { M a t r : c, lMPlEGATl(Matr : c,

Nome : n \

N o m e : n,

Età : e, Stip : S) A

S u P E R V i s i O N E ( l m p i e g a t o : m, Capo : C) A - 3 m ' ( 3 n ' ( 3 e ' ( 3 i ' ( l M P I E G A T I ( M a t r : m', S u P E R V i s i 0 N E ( l m p i e g a t 0 : m',

N o m e : n',

Età : e',

Stip : s') A

Capo : C ) A S ' < 4 0 ) ) ) ) }

Procediamo definendo un predicato per i capi che non soddisfano la condizione: C A P l D l N O N R l C C H I ( C a p o : c) S u P E R V l S l O N E ( l m p i e g a t o : m, Capo : c), l M P l E G A T l ( M a t r : m,

Nome : n,

Età : e, Stip : s), s < 40

"'Per semplicità, in questo paragrafo, usiamo il termine "calcolo relazionale su domini" per riferirci, secondo la discussione già fatta nel Paragrafo 3.2.2, al ".sottoinsieme del calcolo costituito dalle sole espressioni indipendenti dal dominio".

quindi utilizziamo questo predicato in forma negata: C A P I S O L O D I R I C C H I ( M a t r : c,

IMPIEGATI ( M a t r : c,

N o m e : n ) (D,E. F), con vincolo di integrità referenziale fra F e RT, e con cardinalità N 2 = 200 • R 3 (G, H, 1), con cardinalità N 3 = 50 Indicare la cardinalità del risultato di ciascuna delle seguenti espressioni (specificando l'intervallo nel quale essa può variare): 1.

TTAB(R{)

2-

K

3- K

E

( R

2

)

BC(R\)

4. 7T G (« 3 ) 5-

R\MA=DR2

6. /?iN c = d /? 2 7. /? 3 X/=/I*I

8. (/?3lX/=A/fl)«C=D^2 9.

3.4

(RT,MI=ARX)MC=ER2

Date le relazioni R\(A, B, C), R2(E, F. G, //), fl3(./, tf), /f4(L, M) aventi rispettivamente cardinalità N,, N 2 , N 3 e N4 quali vincoli di chiave e di integrità referenziale vanno definiti (se possibile) affinché nei casi seguenti valgano le condizioni indicate? 1.

=

2. \R2MG=BRI\ = NI 3. \7TJ(R3)\ = N3 4. \7Tj(R3)\ < N3

5. \7t L (R 4 )^ L =jR3\ = N 4

6. |/e4«M=JC*3l =

7. | R I M G C = G A : / ? 2 | = N2

8. \R\MBC=GHRZ\ = N\ 9. 0 < \R\MA=FR2\

< NI • N2

10. |/?IIX A = I ./? 2 | = N\ • N2 3.5

Con riferimento ai punti 1 e 2 dell'esercizio precedente, considerando i vincoli di integrità imposti in ogni punto spiegare le differenze che si avrebbero nei risultati delle operazioni nel caso di join destro e join sinistro e come cambia di conseguenza la cardinalità del risultato.

3.6

Considerare lo schema di base di dati contenente le relazioni: FILM(CodiceFilm,Titolo, Regista, Anno,CostoNoleqqio) ARTISTI(Cod ice Attore, Cognome, Nome, Sesso,DataNascita, Nazionalità) INTERPRETAZIONI(Cod iceFi I m,Cod iceAttore, Personaggio) 1. Mostrare una base di dati su questo schema per la quale i join fra le varie relazioni siano tutti completi. 2. Supponendo che esistano due vincoli di integrità referenziale fra la relazione INTERPRETAZIONI e le altre due, discutere i possibili casi di join non completo. 3. Mostrare un prodotto cartesiano che coinvolga relazioni in questa base di dati. 4. Mostrare una base di dati per la quale uno (o più) dei join sia vuoto.

3.7

Con riferimento allo schema nell'Esercizio 3.6, formulare in algebra relazionale, in calcolo su domini, in calcolo su tuple e in Datalog le interrogazioni che trovano: 1. i titoli dei film nei quali Henry Fonda sia stato interprete; 2. i titoli dei film per i quali il regista sia stato anche interprete; 3. i titoli dei film in cui gli attori noti siano tutti dello stesso sesso.

3.8

Si consideri lo schema di base di dati che contiene le seguenti relazioni: DEPUTATI(Codice,Cognome, Nome, Commissione, Provincia,Collegio) COLLEGI (Provincia,Numero,Nome)

PROVINCE

(Sigla,Nome,Regione)

REGIONI

COMMISSIONI

(Codice,Nome)

(Numero,Nome,Presidente)

Formulare in algebra relazionale, in calcolo su domini e in calcolo su tuple le seguenti interrogazioni:

1. trovare nome e cognome dei presidenti di commissioni cui partecipa almeno un deputato eletto in una provincia della Sicilia; 2. trovare nome e cognome dei deputati della commissione Bilancio; 3. trovare nome, cognome e provincia di elezione dei deputati della commissione Bilancio; 4. trovare nome, cognome, provincia e regione di elezione dei deputati della commissione Bilancio; 5. trovare le regioni in cui vi sia un solo collegio, indicando il nome e cognome del deputato ivi eletto; 6. trovare i collegi di una stessa regione in cui siano stati eletti deputati con lo stesso nome proprio. 3.9

Mostrare come le interrogazioni nell'Esercizio 3.8 possano trarre vantaggio, nella specifica, dalla definizione di viste.

3.10 Si consideri lo schema di base di dati sulle relazioni: MATERIE(Codice, Facoltà, Denominazione, Professore) STUDENTI (Matricola, Cognome, Nome, Facoltà) PROFESSORI(Matricola,Cognome,Nome) ESAMI(Studente, Materia, Voto, Data) PIANIDISTUDIO(Studente,Materia,Anno) Formulare, in algebra relazionale, in calcolo su domini, in calcolo su tuple e in Datalog le interrogazioni che producono 1. gli studenti che hanno riportato in almeno un esame una votazione pari a 30, mostrando, per ciascuno di essi, nome e cognome e data della prima di tali occasioni; 2. per ogni insegnamento della facoltà di ingegneria, gli studenti che hanno superato l'esame nell'ultima seduta svolta; 3. gli studenti che hanno superato tutti gli esami previsti dal rispettivo piano di studio; 4. per ogni insegnamento della facoltà di lettere, lo studente (o gli studenti) che hanno superato l'esame con il voto più alto; 5. gli studenti che hanno in piano di studio solo insegnamenti della propria facoltà; 6. nome e cognome degli studenti che hanno sostenuto almeno un esame con un professore che ha il loro stesso nome proprio. 3.11 Con riferimento al seguente schema di base di dati: CITTÀ (Nome, Regione, Abitanti) ATTRAVERSAMENTI(Città, Fiume) FIUMI(Fiume, Lunghezza) formulare, in algebra relazionale, in calcolo su domini, in calcolo su tuple e in Datalog le seguenti interrogazioni:

1. visualizzare nome, regione e abitanti per le città che (i) hanno più di 50.000 abitanti e (ii) sono attraversate dal Po o dall'Adige; 2. trovare le città che sono attraversate da (almeno) due fiumi, visualizzando il nome della città e quello del più lungo di tali fiumi. 3.12 Con riferimento al seguente schema di base di dati: AFFLUENZA ( Affluente, Fiume) FIUMI(Fiume, Lunghezza) formulare l'interrogazione in Datalog che trova tutti gli affluenti, diretti e indiretti dell'Adige. 3.13 Si consideri lo schema relazionale composto dalle seguenti relazioni: PROFESSORI(Codice, Cognome, Nome) CORSI (Codice, Denominazione, Professore) STUDENTI(Matricola, Cognome, Nome) ESAMI(Studente,Corso, Data, Voto) Formulare, con riferimento a tale schema, le espressioni dell'algebra, del calcolo relazionale su tuple e del Datalog, che producano: 1. gli esami superati dallo studente Pico Della Mirandola (supposto unico), con indicazione, per ciascuno, della denominazione del corso, del voto e del cognome del professore; 2. i professori che tengono due corsi (e non più di due), con indicazione di cognome e nome del professore e denominazione dei due corsi. 3.14 Considerare uno schema relazionale contenente le relazioni: R\(ABC),

R2(DG),

R3(EF)

Formulare in calcolo relazionale su tuple e su domini l'interrogazione realizzata in algebra relazionale dalla seguente espressione: ( « 3 M g = £ « 2 ) u PDG^ACW

acef(R\MB=FRI))

3.15 Con riferimento allo stesso schema dell'Esercizio 3.14, formulare in algebra relazionale le interrogazioni realizzate in calcolo su domini dalle seguenti espressioni: {H : g>B •b {A

:

a. B •b

R\(A : a, B : b, C : C) A R2(D : C, G : G)} \

R2(D : a, G : b) A Rì(E : a, F : ¿))

{A : a, B :b

R\(A : a, B \ b, C : c) A 3a'(R\(A : a', B : b, C : c) A a ^ A'))

{A : a, B •b

R\(A : a, B : b,C :c) A Va'(->Ri(A : a',B :b,C : c))va

[A : a. B • b

b,C:c) A Rl(A:a,B: (A:a',B:b,C:c))Aa^

3.16 Facendo riferimento allo schema: R\(AB),

R2(CDE),

Ri(FGH)

= a'} a'}

trasformare la seguente espressione dell'algebra:

H ADH(CT(B=C)A(£=F)A(A>20)A(G=10)((/flM^3)t> 40

Questo predicato sarà vero per le righe in cui l'attributo Stipendio è superiore a 40 mila euro. Richiamando quanto detto nel Paragrafo 3.1.8, osserviamo che ci sono due diverse soluzioni per gestire il caso in cui l'attributo Stipendio abbia valore nullo. La prima soluzione, più immediata e adottata dallo standard SQL89, usa la tradizionale logica a due valori e prevede semplicemente di considerare falso il predicato. La seconda soluzione è invece quella adottata in SQL a partire da SQL-2 e fa uso di una logica a tre valori, in cui un predicato semplice restituisce il valore unknown quando uno qualsiasi dei termini del predicato ha valore nullo. Si noti che il predicato i s n u l i costituisce un'eccezione, restituendo sempre il valore vero o il valore falso, e mai il valore unknown. La differenza tra le soluzioni basate sulle logiche rispettivamente a due e tre valori emerge solo quando si valutano espressioni complicate. In alcuni casi il comportamento del sistema in presenza di valori nulli può diventare molto poco intuitivo, particolarmente quando si costruiscono predicati complessi che usano l'operatore di negazione o interrogazioni nidificate (Paragrafo 4.3.6), richiedendo molta attenzione anche a programmatori esperti. Interpretazione formale delle interrogazioni SQL È possibile costruire una corrispondenza tra le interrogazioni SQL ed equivalenti interrogazioni espresse in algebra relazionale. Data un'interrogazione SQL nella sua forma più semplice: s e l e c t T i . A t t r i b u t O n , . . . , T/,.Attributo,,«, f r o m TABELLAI T I , . . . , TABELLA« T„ w h e r e Condizione si può costruire un'interrogazione equivalente in algebra relazionale utilizzando la seguente traduzione (in cui per semplicità omettiamo le ridenominazioni che ci permettono di considerare tutti i join come prodotti cartesiani): TI .Attributo,

|

T/,.Attributo/,,,,

Condizione(TABELLAi

M

. . . XTABELLA„))

Per interrogazioni SQL più complicate la formula di conversione sopra rappresentata non è più direttamente applicabile. Sarebbe comunque possibile mostrare una tecnica per tradurre ogni interrogazione SQL in una equivalente interrogazione in algebra relazionale, al più utilizzando gli operatori di assegnamento e di ridenominazione. Ancora più stretto è il legame tra SQL e il calcolo relazionale su tuple con dichiarazioni di range (Paragrafo 3.2.3).

Se si assume che le variabili T , , T 2 , T ; , siano presenti nella clausola s e l e c t e che T/, + i, T/, + 2, . . . , T„ non lo siano 4 , la generica istruzione s e l e c t ha una semantica che è uguale a quella della seguente espressione del calcolo relazionale su tuple con dichiarazioni di range: {ri .Attributo] i , . . . ,

Attributo,,», | ^(TABELLA,), . . . , ^(TABELLA/,) | 3 Ì / , + I ( T A B E L L A / , + I ) ( . . . (3R„ ( T a b e l l a , , )

(Condizione'))...)} dove Condizione' è la formula ottenuta da Condizione sostituendo nel modo naturale la notazione SQL a quella usata per il calcolo relazionale. Si può osservare come a ogni alias di tabella corrisponda una variabile del calcolo. Vedremo che questa interpretazione degli alias è in effetti analoga all'interpretazione che dà SQL. Una condizione essenziale per l'esecuzione di queste traduzioni è però che l'interrogazione di partenza non usi funzionalità di SQL non presenti nell'algebra e nel calcolo relazionale, come la valutazione di operatori aggregati (che non abbiamo ancora trattato e che saranno l'oggetto del Paragrafo 4.3.3). I risultati delle interrogazioni SQL differiscono anche dalle espressioni dell'algebra e del calcolo relazionale nella gestione dei duplicati, come discutiamo qui sotto. Duplicati Una significativa differenza tra SQL e algebra relazionale è data dalla gestione dei duplicati. Mentre in algebra una tabella viene vista come una relazione dal punto di vista matematico, e quindi come un insieme di elementi (tuple) diversi tra loro, in SQL si possono avere in una tabella più righe uguali (dette duplicati), ovvero righe con gli stessi valori per tutti gli attributi. Per emulare il comportamento dell'algebra relazionale, sarebbe necessario effettuare l'eliminazione dei duplicati tutte le volte in cui si eseguono operazioni di proiezione. L'operazione di rimozione di duplicati è però molto costosa e spesso non necessaria, in quanto in molti casi il risultato non contiene duplicati. Per esempio, quando il risultato include una chiave per ogni tabella che compare nella clausola f r o m , la tabella risultato non può contenere più esemplari della stessa riga. Per questo in SQL si è stabilito di permettere la presenza di duplicati all'interno delle tabelle, lasciando a chi scrive l'interrogazione il compito di specificare esplicitamente quando l'operazione di rimozione di duplicati è necessaria. L'eliminazione dei duplicati è specificata con la parola chiave d i s t i n c t , da porre immediatamente dopo la parola chiave s e l e c t . La sintassi prevede che si possa anche specificare la parola chiave a l i al posto di d i s t i n c t , indicando che si intendono mantenere tutti i duplicati. L'indicazione della parola a l i è opzionale in quanto, come abbiamo detto, il mantenimento dei duplicati costituisce l'opzione di default.

4 Si noti che è sempre possibile riordinare le variabili in modo tale che questa condizione sia soddisfatta.

PERSONA

CodFiscale

Nome

Cognome

Città

RSSMRA55B21T234J BNCCLR69T30H745Z

Mario Carlo Giovanni Pietro

Rossi Bianchi Rossi Rossi

Verona Roma Verona Milano

RSSGNN41A31B344C RSSPRT75C12F205V Figura 4.14 Tabella PERSONA

D a t a la r e l a z i o n e P E R S Q N A ( C o d F i s c a l e , N o m e , C o g n o m e , C i t t à ) ( F i g u r a 4 . 1 4 ) ,

si vogliono determinare le città in cui abitano persone con cognome "Rossi"; mostriamo due esempi, il primo dei quali ammette la presenza di duplicati mentre il secondo fa uso dell'opzione d i s t i n c t e quindi li rimuove. Interrogazione IO: estrarre le città delle persone il cui cognome è "Rossi", presentando eventualmente più volte lo stesso valore di Città. select Città from Persona w h e r e Cognome

=

'Rossi'

Interrogazione 11: estrarre le città delle persone con cognome "Rossi", facendo comparire ogni città al più una volta. select d i s t i n c t from Persona w h e r e Cognome =

Città 'Rossi'

Eseguendo le due interrogazioni sopra riportate sulla tabella descritta in Figura 4.14, otteniamo i risultati che compaiono in Figura 4.15. Join interni ed esterni Una sintassi alternativa per la specifica dei join (introdotta in SQL-2 e ancora in via di diffusione) permette di distinguere, tra le condizioni che compaiono nell'interrogazione, quelle che rappresentano condizioni di join e quelle che rappresentano condizioni di selezione sulle righe. In tal modo si possono anche specificare le forme esterne dell'operatore di join.

Città

Verona Verona Milano

Città

Verona Milano

La sintassi proposta è la seguente: s e l e c t AttrEspr [ [ a s ] Alias ] {, AttrEspr [ [ a s ] Alias ] } f r o m Tabella [ [ a s ] Alias ] { [ TipoJoin ] j o i n Tabella [ [ a s ] Alias] o n CondizioneDiJoin [ w h e r e AltraCondizione ]

}

Mediante questa sintassi la condizione di join non compare come argomento della clausola w h e r e , ma viene invece spostata nell'ambito della clausola f r o m , associata alle tabelle che vengono coinvolte nel join. Il parametro TipoJoin specifica qual è il tipo di join da usare, e a esso si possono sostituire i termini i n n e r (interno, valore di default che può essere o m e s s o ) , r i g h t o u t e r , l e f t o u t e r o f u l l o u t e r (il q u a l i f i c a t o r e

outer

è opzionale). L ' i n n e r j o i n rappresenta il tradizionale theta-join dell'algebra relazionale. Interrogazione

12: l'Interrogazione 5 può essere riscritta in un modo diverso. s e l e c t from

I.Nome,

Cognome,

Impiegato

I

j o i n

on

=

D.Nome

Dipart

D . C i t t à

Dipartimento

D

Con il join interno le righe che vengono coinvolte nel join sono in generale un sottoinsieme delle righe di ciascuna tabella. Può infatti capitare che alcune righe non vengano considerate in quanto non esiste una corrispondente riga nell'altra tabella per cui la condizione sia soddisfatta. Questo comportamento spesso non rispetta le esigenze delle applicazioni, le quali, alla eliminazione delle righe operata dal join, possono preferire di mantenere le righe, introducendo dei valori nulli per rappresentare l'assenza di informazioni provenienti dall'altra tabella. Come abbiamo visto nel Paragrafo 3.1.5, il join esterno ( o u t e r j o i n ) esegue un join mantenendo però tutte le righe che fanno parte di una o entrambe le tabelle coinvolte. Esistono appunto tre varianti dei join esterni: l e f t , r i g h t e f u l l . Il l e f t j o i n fornisce come risultato il join interno esteso con le righe della tabella che compare a sinistra per le quali non esiste una corrispondente riga nella tabella di destra; il r i g h t j o i n si comporta in modo simmetrico (conserva le righe escluse delia tabella di destra); infine, il f u l l j o i n restituisce il join interno esteso con le righe escluse di entrambe le tabelle. Si considerino le tabelle G U I D A T O R E e A U T O M O B I L E rappresentate in Figura 4.16. Interrogazione 13: estrarre i guidatori con le automobili loro associate, mantenendo nel risultato anche i guidatori senza automobile. s e l e c t

Nome,

Cognome,

Targa, from

Guidatore

Marca, G

l e f t

G.NroPatente, Modello j o i n

Automobile

(G.NroPatente=A.NroPatente)

A

on

GUIDATORE

AUTOMOBILE

Nome

Cognome

NroPatente

Mario Carlo Marco

Rossi Bianchi Neri

VR 2030020Y PZ 1012436B AP 4544442R

Targa

Marca

Modello

AB 574 WW AA 652 FF BJ 747 XX BB421 JJ

Fiat Fiat Lancia Fiat

Punto Brava Delta Uno

NroPatente

VR VR PZ MI

2030020Y 2030020Y 1012436B 2020030U

Figura 4.16 Tabelle GUIDATORE e AUTOMOBILE

Il risultato compare in Figura 4.17. Si noti come l'ultima riga del risultato rappresenti un guidatore cui non risulta associata nessuna automobile. Interrogazione 14: estrarre tutti i guidatori e tutte le auto, mostrando tutte le relazioni esistenti tra di essi. select

Nome, C o g n o m e , G . N r o P a t e n t e , Targa, Marca, Modello f r o m G u i d a t o r e G f u l l j o i n A u t o m o b i l e A on (G.NroPatente=A.NroPatente)

L'interrogazione produce come risultato la tabella in Figura 4.18. Si noti che l'ultimo elemento della tabella descrive un'automobile per la quale non esiste un corrispondente elemento in G U I D A T O R E . In alcune implementazioni di SQL si rappresenta il join esterno aggiungendo all'identificativo degli attributi un particolare carattere o sequenza di caratteri (per esempio * o ( + ) ). In questo modo diventa possibile formulare il join esterno senza ricorrere alla sintassi che abbiamo visto.

Nome

Cognome

Mario Mario Carlo Marco

Rossi Rossi Bianchi Neri

G.NroPatente

VR VR PZ AP

2030020Y 2030020Y 1012436B 4544442R

Targa

Marca

Modello

AB 574 WW AA 652 FF BJ 747 XX

Fiat Fiat Lancia

Punto Brava Delta

NULL

NULL

NULL

Nome

Cognome

Mario Mario Carlo Marco

Rossi Rossi Bianchi Neri

NULL

NULL

G.NroPatente VR VR PZ AP

2030020Y 2030020Y 1012436B 4544442R NULL

Targa

Marca

Modello

AB 574 W W AA 652 FF BJ 747 X X

Fiat Fiat Lancia

Punto Brava Delta

NULL

NULL

NULL

BB 421 JJ

Fiat

Uno

Figura 4.18 Risultato dell'Interrogazione 14

Interrogazione diverso.

15: l'Interrogazione 13 potrebbe essere formulata in un modo

select

Nome, Cognome, G.NroPatente, Targa, Marca, Modello f r o m G u i d a t o r e G, A u t o m o b i l e A where G.NroPatente * = A.NroPatente

Queste soluzioni sono però al di fuori dello standard SQL e non sono perciò portabili da un sistema all'altro. Un'ulteriore estensione di SQL-2 permette di far precedere a ogni join la parola chiave n a t u r a i . In questo modo si consente la specifica del join naturale dell'algebra relazionale, che prevede di utilizzare nel join di due tabelle lina condizione implicita di uguaglianza su tutti gli attributi caratterizzati dallo stesso nome (Paragrafo 3.1.5). Per esempio, la query 14 potrebbe essere rappresentata come: Interrogazione

16:

select from

Nome, Cognome, G.NroPatente, Targa, Marca, Modello Guidatore G naturai f u l l join Automobile

Nonostante il vantaggio di una rappresentazione più compatta, il join naturale non è normalmente consigliabile (e spesso non è offerto dai sistemi commerciali). Un motivo è che un'interrogazione che usa il join naturale può introdurre dei rischi nelle applicazioni, in quanto il suo comportamento può mutare profondamente al variare dello schema delle tabelle. Uso di variabili Abbiamo già visto come nelle interrogazioni SQL sia possibile associare un nome alternativo, detto alias, alle tabelle che compaiono come argomento della clausola f r o m . Il nome viene usato per far riferimento alla tabella nel contesto dell'interrogazione. Questa funzionalità può essere sfruttata per far riferimento a una tabella in modo compatto, ricorrendo a brevi alias ed evitando così di scrivere per esteso il nome della tabella tutte le volte che ne viene richiesto l'uso (Interrogazione 5). Vi sono però altre ragioni per usare gli alias.

Per prima cosa, utilizzando 100

as

SommaStipendi

Applicando l'interrogazione alla tabella rappresentata in Figura 4.21, si procede seguendo gli stessi passi descritti per le interrogazioni con g r o u p b y . Dopo aver raggruppato le righe in base al valore dell'attributo Dipart, viene valutato il predicato argomento della clausola h a v i n g , che seleziona i dipartimenti per cui la somma degli stipendi, per tutti gli elementi del sottoinsieme, è superiore a 100 mila euro. Il risultato dell'interrogazione è rappresentato dalla tabella in Figura 4.25.

Dipart

SommaStipendi

Amministrazione Direzione

125 153

Figura 4.25 Risultato dell'Interrogazione 31

La sintassi permette anche la definizione di interrogazioni che presentano la clausola h a v i n g senza una corrispondente clausola g r o u p b y . In questo caso, l'intero insieme di righe è trattato come un unico raggruppamento, ma questo ha in generale un limitato campo di applicabilità, perché, se la condizione non è soddisfatta, il risultato sarà vuoto. Come la clausola w h e r e , anche la clausola h a v i n g ammette come argomento un'espressione booleana su predicati semplici. I predicati semplici sono normalmente confronti tra il risultato della valutazione di un operatore aggregato e una generica espressione; sintatticamente è ammessa anche la presenza diretta degli attributi argomento della g r o u p b y , ma è preferibile raccogliere tutte le condizioni su questi attributi nell'ambito della clausola w h e r e . Per sapere quali predicati di un'interrogazione che fa uso del raggruppamento vanno dati come argomento della clausola w h e r e e quali come argomento della clausola h a v i n g , basta rispettare il seguente criterio: solo i predicati in cui compaiono operatori aggregati devono essere argomento della clausola h a v i n g . Interrogazione 32: estrarre i dipartimenti per cui la media degli stipendi degli impiegati che lavorano nell'ufficio 20 è superiore a 25 mila euro. select

Dipart

from Impiegato w h e r e U f f i c i o = 20 group by Dipart having avg(Stipendio)

>25

La forma sintetica generale di un'interrogazione SQL diventa (riassumendo i vari arricchimenti che abbiamo apportato nei paragrafi precedenti): SelectSQL ::= s e l e c t

ListaAttributiOEspressioni

from ListaTabelle [ w h e r e CondizioniSemplici ] [ g r o u p b y ListaAttributiDiRaggruppamento [ h a v i n g CondizioniAggregate ] [ o r d e r b y ListaAttributiDiOrdinamento

] ]

4.3.5 Interrogazioni di tipo insiemistico SQL mette a disposizione anche degli operatori insiemistici, simili a quelli disponibili nell'algebra relazionale. Gli operatori disponibili sono gli operatori di

u n i o n (unione), i n t e r s e c t (intersezione) ed e x c e p t (chiamato anche m i n u s , differenza), di significato analogo ai corrispondenti operatori dell'algebra relazionale. Si noti che ogni interrogazione che faccia uso degli operatori i n t e r s e c t ed except può essere espressa utilizzando altri costrutti del linguaggio (tipicamente tramite interrogazioni nidificate, argomento del Paragrafo 4.3.6). Al contrario, come è già stato discusso nel Paragrafo 3.2.3 parlando del calcolo relazionale con dichiarazioni di range, l'operatore di unione arricchisce il potere espressivo di SQL e permette di scrivere interrogazioni altrimenti non formulabili. La sintassi per l'uso degli operatori insiemistici è la seguente: SelectSQL

{( u n i o n

|

intersect

| e x c e p t ) [ a l i ] SelectSQL

}

Gli operatori insiemistici, al contrario del resto del linguaggio, assumono come default di eseguire una eliminazione dei duplicati. Ci sono due ragioni che giustificano questa differenza: in primo luogo, l'eliminazione dei duplicati rispetta molto meglio il tipico significato di questi operatori; in secondo luogo, l'esecuzione di queste operazioni (in particolare differenza e intersezione) richiede di effettuare un'analisi delle righe che rende molto limitato il costo aggiuntivo della eliminazione dei duplicati. Qualora nell'interrogazione si voglia adottare una diversa interpretazione degli operatori e si vogliano utilizzare gli operatori insiemistici che preservano i duplicati, sarà sufficiente utilizzare l'operatore con la parola chiave a l i . Negli esempi successivi confrontiamo il comportamento ottenuto usando l'una e l'altra delle scelte. Un'altra osservazione è che SQL non richiede che gli schemi su cui vengono effettuate le operazioni insiemistiche siano identici (come è invece richiesto dall'algebra relazionale), ma solo che gli attributi siano in pari numero e che abbiano domini compatibili. La corrispondenza tra gli attributi non si basa sul nome ma sulla posizione degli attributi. Se gli attributi hanno nome diverso, il risultato normalmente usa i nomi del primo operando. Interrogazione

33: estrarre i nomi e i cognomi degli impiegati. select Nome from Impiegato union select Cognome from Impiegato

L'interrogazione ottiene dapprima i valori dell'attributo Nome per le righe di IMPIEGATO, ricava quindi i valori dell'attributo Cognome per le stesse righe, e infine costruisce la tabella risultato unendo i due risultati parziali. Visto che le operazioni insiemistiche eliminano i duplicati, non vi saranno elementi ripetuti nella tabella risultato, nonostante la presenza di duplicati in entrambe le tabelle di partenza, e nonostante la presenza di alcuni valori identici in entrambe le tabelle. Supponendo che i dati di partenza siano quelli contenuti nella tabella in Figura 4.21, il risultato della valutazione dell'interrogazione è rappresentato in Figura 4.26.

Nome

Mario Carlo Giovanni Franco Lorenzo Paola Marco Rossi Bianchi Verdi Neri Gialli Rosati Figura 4.26 Risultato dell'Interrogazione 33 Interrogazione 34: estrarre i nomi e i cognomi di tutti gli impiegati, eccetto quelli appartenenti al dipartimento Amministrazione, mantenendo i duplicati. select Nome from Impiegato w h e r e D i p a r t union a l i select Cognome from Impiegato w h e r e D i p a r t

'Amministrazione'

'Amministrazione'

In questo caso tutti i duplicati vengono tenuti e il risultato della query, sempre partendo dalla tabella in Figura 4.21, è quello rappresentato in Figura 4.27. assBgs Nome

Carlo Franco Carlo Lorenzo Marco Bianchi Neri Rossi Gialli Franco

Nome Franco Figura 4.28 Risultato dell'Interrogazione 35

Interrogazione

35: estrarre i cognomi di impiegati che sono anche nomi. select Nome from Impiegato intersect select Cognome from Impiegato

Si ottiene da questa interrogazione il semplice risultato in Figura 4.28. Interrogazione 36: estrarre i nomi degli impiegati che non sono cognomi di qualche impiegato. select Nome from Impiegato except select Cognome from Impiegato

11 risultato di questa interrogazione è mostrato in Figura 4.29.

4.3.6 Interrogazioni nidificate Fino a ora abbiamo visto interrogazioni in cui l'argomento della clausola w h e r e si basa su condizioni composte (tramite gli operatori logici a n d , o r e n o t ) da predicati semplici, in cui ciascun predicato rappresenta un semplice confronto tra

Nome Mario Carlo Giovanni Lorenzo Paola Marco

due valori. SQL ammette anche l'uso di predicati con una struttura più complessa, in cui si confronta un valore (ottenuto come risultato di una espressione valutata sulla singola riga) con il risultato dell'esecuzione di un'interrogazione SQL. L'interrogazione che viene usata per il confronto viene definita direttamente nel predicato interno alla clausola w h e r e . Si parla in questo caso di interrogazioni nidificate. Nel caso più tipico, l'espressione che compare come primo membro del confronto è il semplice nome di un attributo. Se in un predicato si confronta un attributo con il risultato di un'interrogazione, sorge il problema di disomogeneità dei termini del confronto. Infatti, da una parte abbiamo il risultato dell'esecuzione di un'interrogazione SQL (in generale un insieme di valori), mentre dall'altra abbiamo il valore dell'attributo per la particolare riga. La soluzione offerta da SQL consiste nell'estendere, con le parole chiave a l i o a n y , i normali operatori di confronto (=, , , =). La parola chiave a n y specifica che la riga soddisfa la condizione se risulta vero il confronto (con l'operatore specificato) tra il valore dell'attributo per la riga e almeno uno degli elementi restituiti dall'interrogazione. La parola chiave a l i invece specifica che la riga soddisfa la condizione solo se tutti gli elementi restituiti dall'interrogazione nidificata rendono vero il confronto. La sintassi richiede la compatibilità di dominio tra l'attributo restituito dalla interrogazione nidificata e l'attributo con cui avviene il confronto. Interrogazione Firenze.

37: estrarre gli impiegati che lavorano in dipartimenti situati a

select * from Impiegato where Dipart = any

(select Nome from Dipartimento where Città = 'Firenze')

L'interrogazione seleziona le righe di IMPIEGATO per cui il valore dell'attributo Dipart è uguale ad almeno uno dei valori dell'attributo Nome delle righe di DIPARTIMENTO.

Questa interrogazione poteva anche essere espressa mediante un join tra le tabelle IMPIEGATO e DIPARTIMENTO, e in effetti gli ottimizzatori sono generalmente in grado di trattare allo stesso modo le due diverse formulazioni di questa interrogazione. La scelta tra l'una e l'altra rappresentazione può essere dettata dal grado di leggibilità della soluzione. In casi così semplici non vi sono differenze significative, ma per interrogazioni più complicate la scomposizione in interrogazioni distinte può migliorare la leggibilità. Consideriamo un'interrogazione che permette di trovare gli impiegati che hanno lo stesso nome di un impiegato del dipartimento Produzione. L'interrogazione ammette due formulazioni. La prima è più compatta e fa uso di variabili.

Interrogazione

38: select

II.Nome

from Impiegato II, Impiegato 12 where II.Nome = 12.Nome and 12.Dipart = 'Produzione'

La seconda interrogazione fa uso di un'interrogazione nidificata, risolvendo l'interrogazione senza bisogno di introdurre alias. Interrogazione

39:

s e l e c t from where

Nome Impiegato Nome

=

any

( s e l e c t from

Nome Impiegato

where

Dipart

=

'Produzione')

Consideriamo ora una diversa interrogazione. Interrogazione 40: estrarre i dipartimenti in cui non lavorano persone di cognome "Rossi". s e l e c t from where

Nome Dipartimento Nome

a l i

( s e l e c t from

Dipart Impiegato

where

Cognome

=

' R o s s i ' )

L'interrogazione nidificata seleziona i valori di Dipart di tutte le righe in cui il cognome vale "Rossi". La condizione è quindi soddisfatta da quelle righe di DIPARTIMENTO per cui il valore dell'attributo Nome non fa parte dei nomi prodotti dall'interrogazione nidificata. Questa interrogazione non poteva essere espressa mediante un join. È interessante notare che tale interrogazione poteva essere implementata in algebra relazionale con l'espressione (7TN0me(DlPARTlMENTO) — 7TDipart (o r Cognome= «o™ ( l M P l E G A T O ) ) ) , e quindi poteva anche essere espressa tramite l'operatore insiemistico e x c e p t : Interrogazione

41: s e l e c t from

Nome Dipartimento

except s e l e c t from where

Dipart Impiegato Cognome

=

'Rossi'

Per rappresentare il controllo di appartenenza e di esclusione rispetto a un insieme, SQL mette a disposizione due appositi operatori, i n e n o t i n , i quali risultano

d e l t u t t o i d e n t i c i a g l i o p e r a t o r i c h e a b b i a m o v i s t o nei d u e p r e c e d e n t i e s e m p i . = a n y e < > a l i . M o s t r e r e m o e s e m p i d e l l o r o u s o nel p r o s s i m o p a r a g r a f o .

Si può osservare infine come in alcuni casi interrogazioni che fanno uso degli operatori max e m i n possono essere rappresentate senza gli operatori stessi, tramite un uso opportuno delle interrogazioni nidificate. Interrogazione 42: estrarre il dipartimento dell'impiegato che guadagna lo stipendio massimo (usando l'operatore aggregato max). select Dipart from Impiegato where Stipendio = any (select max(Stipendio) from Impiegato)

Interrogazione 43: estrarre il dipartimento dell'impiegato che guadagna lo stipendio massimo (usando solo un'interrogazione nidificata). s e l e c t Dipart from Impiegato w h e r e S t i p e n d i o >= a l i (select Stipendio from Impiegato)

Le due interrogazioni sono equivalenti, in quanto il valore massimo è esattamente il valore che è superiore o uguale a tutti i valori dello stesso attributo nelle altre righe della relazione. In questi casi è comunque consigliabile l'utilizzo dell'operatore aggregato, che fornisce un'interrogazione più leggibile (e può essere implementato da qualche sistema in modo più efficiente). È anche interessante notare che nella prima interrogazione è indifferente usare le parole chiave a n y o a l i , poiché l'interrogazione nidificata restituisce sempre un unico valore; in effetti, la sintassi in quel caso ammette anche l'omissione della parola chiave a n y . Interrogazioni nidificate complesse Una interpretazione molto semplice e intuitiva delle interrogazioni nidificate consiste nell'assumere che l'interrogazione nidificata venga eseguita prima di analizzare le righe dell'interrogazione esterna. Il risultato dell'interrogazione può essere salvato in una tabella temporanea e il controllo sulle righe dell'interrogazione esterna può essere fatto accedendo direttamente al risultato temporaneo. Questa interpretazione corrisponde tra l'altro a un meccanismo di esecuzione efficiente, in cui l'interrogazione nidificata viene eseguita una sola volta. Consideriamo ancora l'Interrogazione 40. 11 sistema può eseguire dapprima l'interrogazione nidificata, che estrae il valore dell'attributo D i p a r t per tutti gli impiegati di cognome "Rossi". Dopo aver fatto ciò, per ciascun dipartimento si controlla che il nome non sia incluso nella tabella prodotta, utilizzando l'operatore a l i .

Talvolta però l'interrogazione nidificata fa riferimento al contesto dell'interrogazione che la racchiude; tipicamente ciò accade tramite una variabile definita nell'ambito della query più esterna e usata nell'ambito della query più interna (si parla di un passaggio di binding da un contesto all'altro). La presenza del meccanismo di passaggio di binding arricchisce il potere espressivo di SQL. In questo caso l'interpretazione semplice data precedentemente alle query nidificate non vale più; bisogna a questo punto riconsiderare l'interpretazione standard delle interrogazioni SQL, per cui prima si costruisce il prodotto cartesiano delle tabelle e successivamente si applicano a ciascuna riga del prodotto le condizioni che compaiono nella clausola w h e r e . L'interrogazione nidificata è un componente della clausola w h e r e e dovrà anch'essa essere valutata separatamente per ogni riga prodotta nella valutazione della query esterna. Così, la nuova interpretazione è la seguente: per ogni riga della query esterna, valutiamo per prima cosa la query nidificata, quindi calcoliamo il predicato a livello di riga sulla query esterna. Tale processo può essere ripetuto un numero arbitrario di volte, pari al numero arbitrario di nidificazioni che possono essere utilizzate nella query; con query cosi complicate si perdono però le caratteristiche di leggibilità delle interrogazioni SQL. Per quanto riguarda la visibilità (o scope) delle variabili SQL, vale la restrizione che una variabile è usabile solo nell'ambito della query in cui è definita o nell'ambito di una query nidificata (a un qualsiasi livello) all'interno di essa. Se un'interrogazione possiede interrogazioni nidificate allo stesso livello (su predicati distinti), le variabili introdotte nella clausola f r o m di una query non potranno essere usate nell'ambito dell'altra query. Una interrogazione come la seguente, per esempio, è scorretta: Interrogazione 44: estrarre gli impiegati che afferiscono al dipartimento Produzione o a un dipartimento che risiede nella stessa città del dipartimento Produzione (query scorretta). s e l e c t * from Impiegato where Dipart in

Dipart

in

(selec from where (selec from where

t Nome Dipartimento Di Nome = ' P r o d u z i o n e ' ) t Nome D i p a r t i m e n t o D2 D i . C i t t à

=

or

D2.Città)

La query non rispetta la sintassi SQL perché utilizza la variabile D i dove non è visibile. Introduciamo ora l'operatore logico e x i s t s . Questo operatore ammette come parametro un'interrogazione nidificata e restituisce il valore vero solo se l'interrogazione fornisce un risultato non vuoto (corrisponde al quantificatore esistenziale della logica). Questo operatore può essere usato in modo significativo solo quando si ha un passaggio di binding tra l'interrogazione esterna e quella nidificata.

Si consideri una relazione che descrive dati anagrafici, avente il seguente schema: P E R S O N A ) C o d F i s c a l e , N o m e , C o g n o m e , Città).

Interrogazione 45: estrarre le persone che hanno degli omonimi (ovvero persone con lo stesso nome e cognome, ma diverso codice fiscale). select * from Persona where e x i s t s

P (select * f r o m P e r s o n a PI w h e r e PI.Nome = P.Nome a n d PI.Cognome = P.Cognome and P i . C o d F i s c a l e P . C o d F i s c a l e )

L'interrogazione ricerca le righe della tabella PERSONA per le quali esiste un'ulteriore riga in PERSONA con lo stesso Nome e Cognome, ma diverso CodFiscale. Si può osservare che in questo caso non risulta possibile eseguire l'interrogazione nidificata prima di valutare l'interrogazione più esterna, in quanto senza avere associato un valore alla variabile P l'interrogazione nidificata non risulta completamente definita. Si richiede invece che venga prima valutata l'interrogazione esterna; per ogni singola riga esaminata nell'ambito dell'interrogazione esterna si deve valutare l'interrogazione nidificata. Così, nell'esempio, prima di tutto verranno considerate una a una le righe associate alla variabile P; per ciascuna di queste righe sarà poi eseguita l'interrogazione nidificata che restituirà o meno l'insieme vuoto a seconda che vi siano o meno degli omonimi della persona. Questa interrogazione si sarebbe potuta formulare anche con un join tra due diverse istanze della tabella PERSONA. Interrogazione nidificata).

46: estrarre le persone che hanno degli omonimi (senza query

s e l e c t P.* f r o m P e r s o n a P, P e r s o n a P I w h e r e P I . N o m e = P.Nome a n d PI.Cognome = P.Cognome and P I . C o d F i s c a l e P . C o d F i s c a l e ) Presentiamo ora la richiesta opposta alla precedente. Interrogazione 47: estrarre le persone che non hanno degli omonimi. select * from Persona P where not e x i s t s

(select * from P e r s o n a PI w h e r e PI.Nome = P.Nome a n d PI.Cognome = P.Cognome and P I . C o d F i s c a l e P . C o d F i s c a l e )

L'intepretazione è analoga a quella dell'Interrogazione 45, con l'unica differenza che il predicato è soddisfatto nel caso che il risultato dell'interrogazione nidificata sia vuoto. Questa interrogazione poteva anche essere implementata con una differenza che sottraesse ai nomi e cognomi delle persone i nomi e cognomi delle persone che possiedono un omonimo, determinati tramite un join. Un altro modo per formulare la stessa interrogazione può far uso del costruttore di tupla, rappresentato da una coppia di parentesi tonde che racchiudono la lista di attributi. Interrogazione

48: estrarre le persone che non hanno degli omonimi.

select * from Persona P where (Nome, Cognome) n o t in ( s e l e c t Nome, Cognome from Persona Q w h e r e Q . C o d F i s c a l e

P.CodFiscale)

Si consideri una base di dati con una tabella CANTANTE(Nome,Canzone) e una tabella AuTQRE(Nome,Canzone). Interrogazione 49: estrarre i cantautori puri, ovvero i cantanti che hanno eseguito solo canzoni di cui erano anche autori. select Nome from Cantante w h e r e Nome n o t in ( s e l e c t Nome from Cantante C w h e r e Nome n o t in (select Nome from Autore where Autore.Canzone=C.Canzone))

La prima interrogazione nidificata ( s e l e c t Nome f r o m C a n t a n t e C . . . ) non ha alcun legame con l'interrogazione esterna, e può quindi essere eseguita in modo del tutto indipendente. L'interrogazione al livello successivo invece presenta un legame ( A u t o r e . C a n z o n e = C . C a n z o n e ) . L'esecuzione dell'interrogazione può così avvenire seguendo queste fasi. 1. L'interrogazione s e l e c t Nome f r o m C a n t a n t e C . . . legge tutte le righe della tabella CANTANTE. 2. Per ognuna delle righe di C viene valutata l'interrogazione più interna, che restituisce i nomi degli autori della canzone il cui titolo compare nella riga di C che viene considerata. Se il nome del cantante non compare tra gli autori (e quindi il cantante non è un cantautore puro), allora il nome viene selezionato.

3. Dopo che l'interrogazione nidificata ha terminato di analizzare le righe di C, costruendo la tabella contenente i nomi dei cantanti che non sono cantautori puri, viene eseguita l'interrogazione più esterna, la quale restituirà tutti i nomi di cantanti che non compaiono nella tabella ottenuta come risultato dell'interrogazione nidificata. La correttezza di questa esecuzione appare evidente se si considera che la query può essere espressa in modo equivalente tramite l'operatore insiemistico e x c e p t : Interrogazione

50:

s e l e c t Nome from Cantante except s e l e c t Nome from Cantante C w h e r e Nome n o t i n

( s e l e c t Nome from Autore where Autore.Canzone=C.Canzone)

Si noti che non è affatto detto che i sistemi SQL commerciali eseguano al loro interno l'interrogazione scandendo sempre la tabella esterna e producendo un'interrogazione per ogni riga di questa relazione. I sistemi cercano anzi di eseguire il più possibile le interrogazioni in un modo set-oriented (ovvero orientato agli insiemi), con l'obiettivo di effettuare poche operazioni su tanti dati. Per far questo, il sistema può trasformare l'interrogazione e cercare di applicare diverse ottimizzazioni, come la memorizzazione dei risultati delle query nidificate, o la scelta di un opportuno ordine di valutazione dei predicati.

4.4 Modifica dei dati in SQL La parte di Data Manipulation Language comprende i comandi per interrogare e modificare il contenuto della base di dati. I comandi che permettono di modificare la base di dati sono i n s e r t , d e l e t e e u p d a t e . Analizziamo separatamente i singoli comandi, anche se, come vedremo, sono tutti caratterizzati da uno schema simile.

4.4.1 Inserimento Il comando di inserimento di righe nella base di dati presenta due sintassi alternative: insert

i n t o NomeTabella [ Li staAttributi ] { v a l u e s ( ListaValori ) | SelectSQL )

La prima forma permette di inserire singole righe all'interno delle tabelle. L'argomento della clausola v a l u e s rappresenta esplicitamente i valori degli attributi della singola riga. Per esempio: insert

into

Dipartimento(NomeDip,Città) values('Produzione','Torino')

La seconda forma invece permette di aggiungere degli insiemi di righe, estratti dal contenuto della base di dati. Il seguente comando inserisce nella tabella PRODOTTlMlLANESl il risultato della selezione dalla relazione PRODOTTO di tutte le righe aventi "Milano" come valore dell'attributo LuogoProd. insert

into ProdottiMilanesi (select Codice, Descrizione from Prodotto where LuogoProd = 'Milano')

Ciascuna forma del comando possiede uno specifico campo di applicazione. La prima forma è quella tipicamente usata all'interno dei programmi per riempire una tabella con i dati forniti direttamente dagli utenti. Ogni uso del comando di i n s e r t è generalmente associato al riempimento di una maschera (oform), ovvero un'interfaccia di facile uso in cui all'utente vengono presentati sul video il nome dei vari attributi e appositi spazi in cui immettere i relativi valori. La seconda forma permette invece di inserire dati in una tabella a partire da altre informazioni presenti nella base di dati. Se in un inserimento non vengono specificati i valori di tutti gli attributi della tabella, agli attributi mancanti viene assegnato il valore di default, o in assenza di questo il valore nullo; come è stato già detto nel Paragrafo 4.2.6, se l'inserimento viola un vincolo di not nuli definito sull'attributo, l'inserimento viene rifiutato. Si noti infine che la corrispondenza tra gli attributi della tabella e i valori da inserire è data dall'ordine in cui compaiono i termini nella definizione della tabella. Perciò, al primo attributo che compare in ListaValori (per la prima forma del comando) o al primo elemento della clausola s e l e c t (per la seconda forma) deve corrispondere il primo attributo che compare in ListaAttrihuti (o nella definizione della tabella se ListaAttrihuti è omesso), e così via per gli altri attributi.

4.4.2 Cancellazione 11 comando d e l e t e elimina righe dalle tabelle della base di dati, seguendo la semplice sintassi: delete

f r o m N o m e T a b e l l a [ w h e r e Condizione

]

Quando la condizione argomento della clausola w h e r e non viene specificata, il comando cancella tutte le righe dalla tabella, altrimenti vengono rimosse solo le

righe che soddisfano la condizione. Si ricorda che qualora esista un vincolo di integrità referenziale con politica di c a s c a d e in cui la tabella viene referenziata, allora la cancellazione di righe dalla tabella può comportare la cancellazione di righe appartenenti ad altre tabelle (e si può generare una reazione a catena se queste cancellazioni a loro volta causano la cancellazione di righe di altre tabelle). delete

from Dipartimento w h e r e NomeDip = 'Produzione'

Il comando elimina la riga di DIPARTIMENTO avente nome "Produzione" (visto che NomeDip era stata dichiarata come p r i m a r y k e y della tabella, vi può essere una sola riga avente quel valore). La condizione rispetta la sintassi della s e l e c t , per cui possono comparire al suo interno anche interrogazioni nidificate che fanno riferimento ad altre tabelle. Un semplice esempio è il comando che elimina i dipartimenti senza impiegati: delete

from Dipartimento w h e r e Nome n o t i n

(select Dipart from Impiegato)

Si noti la differenza tra il comando d e l e t e appena visto e il comando d r o p descritto nel Paragrafo 4.2.8. Un comando come: delete

from

Dipartimento

elimina tutte le righe dalla tabella DIPARTIMENTO, eventualmente eliminando anche tutte le righe dalle tabelle che sono legate da vincolo di integrità referenziale con la tabella, se per il vincolo è specificata la politica c a s c a d e sull'evento di cancellazione. Lo schema della base di dati rimane però immutato, e il comando modifica solamente l'istanza della base di dati. Il comando: drop

table

Dipartimento

cascade

ha lo stesso effetto del comando d e l e t e , ma in più anche lo schema della base di dati viene modificato, eliminando dallo schema non solo la tabella DIPARTIMENTO, ma anche tutte le viste e tabelle che nella loro definizione fanno riferimento a essa. Invece, il comando:

drop

table

Dipartimento

r e s t r i c t

4.4.3

Modifica

Il comando di u p d a t e presenta una sintassi leggermente più complicata: u p d a t e NomeTabella s e t Attributo = { Espressione | SelectSQL | n u l i | d e f a u l t ) {, Attributo = ( Espressione \ SelectSQL | n u l i | d e f a u l t ) } [ w h e r e Condizione ] Il comando di u p d a t e permette di aggiornare uno o più attributi delle righe di NomeTabella che soddisfano l'eventuale Condizione. Se il comando non presenta la clausola w h e r e , come al solito si suppone che la condizione sia soddisfatta e si esegue la modifica su tutte le righe. Il nuovo valore cui viene posto l'attributo può essere: 1. il risultato della valutazione di un'espressione sugli attributi della tabella, che può anche far riferimento al valore corrente dell'attributo che verrà modificato dal comando; 2. il risultato di una generica interrogazione SQL; 3. il valore nullo; 4. il valore di default per il dominio. Il comando: update

Dipendente set Stipendio = where Matricola

StipendioBase = 'M2047'

+

5

opera su una singola riga, aggiornando lo stipendio del dipendente con matricola M2047, mentre l'esempio successivo opera su un insieme di righe: update

Impiegato set Stipendio = Stipendio * 1.1 where Dipart = 'Amministrazione'

Il comando aumenta del 10% lo stipendio di tutti gli impiegati che lavorano in Amministrazione. L'operatore di assegnamento = ha un comportamento analogo a quello dei normali linguaggi di programmazione, per cui S t i p e n d i o sul lato destro dell'operatore rappresenta il vecchio valore dell'attributo, valutato per ogni riga su cui deve essere applicato l'aggiornamento. Il risultato dell'espressione diventa il nuovo valore dell'attributo. La natura set-oriented di SQL presenta alcune particolarità di cui bisogna tenere conto quando si scrivono comandi di aggiornamento. Supponiamo che si vogliano modificare gli stipendi dei dipendenti, aumentando del 10% gli stipendi

sotto i 30 mila euro, e del 15% gli stipendi superiori. Un modo per aggiornare in questo modo la base di dati consiste nell'eseguire questo comando: update

update

Impiegato set Stipendio = where Stipendio

Stipendio < = 3 0

*

1.1

Impiegato set Stipendio = where Stipendio

Stipendio >30

*

1.15

Il problema di questa soluzione è che se consideriamo un dipendente con uno stipendio iniziale di 30 mila euro, questo soddisferà la condizione del primo comando di aggiornamento, per cui l'attributo Stipendio verrà posto pari a 33 mila euro. Ma a questo punto la riga soddisferà anche le condizioni del secondo comando di aggiornamento, per cui lo stipendio sarà di nuovo modificato. Il risultato finale è che per questa riga l'aumento complessivo risulta del 26,5%, violando quindi i requisiti di partenza. Il problema ha origine nel carattere set-oriented di SQL. Con un linguaggio tuple-oriented sarebbe possibile analizzare le righe una a una e applicare o l'una o l'altra delle modifiche a seconda del valore dello stipendio. In questo caso una semplice soluzione consiste nell'invertire l'ordine di esecuzione dei due comandi, aumentando prima gli stipendi superiori e poi i rimanenti. In casi più complicati la soluzione può introdurre degli aggiornamenti intermedi, fare uso del costrutto c a s e (Paragrafo 5.2.2) o cambiare completamente approccio e scrivere un programma in un tradizionale linguaggio di programmazione di alto livello, realizzando all'interno del programma, per esempio tramite l'uso di cursori, gli aggiornamenti desiderati (descriveremo il funzionamento dei cursori nel Paragrafo 6.3.1).

4.5 Esempi riepilogativi 1. Dato il seguente schema relazionale che descrive il calendario di una manifestazione sportiva a squadre nazionali: STADIO( N o m e , C i t t à , C a p i e n z a ) LNCQNTRO(NomeStadio,Data,Ora,Squadra1,Squadra2) NAZIONALE(Paese,Continente,Categoria)

Esprimere in SQL le seguenti interrogazioni: (a) Estrarre i nomi degli stadi in cui non gioca nessuna nazionale europea.

Soluzione: select Nome from Stadio w h e r e Nome n o t in (select NomeStadio from Incontro where (Squadrai in (select Paese from Nazionale where Continente or (Squadra2 in (select Paese from Nazionale where Continente

=

'Europa'

))

=

'Europa'

)))

(b) Esprimere l'interrogazione in algebra relazionale, in calcolo e in Datalog. Soluzione: i. Algebra relazionale: NOME (STADIO) NomeStadio ( ( 7Z*paeSe ( ° Continente= Europa N A Z I O N A L E ) ) ^Squadrai =PaesevSquadra2=Paese ( 7T NomeStadio.Squadrai .Squadra2 ( I N C O N T R O ) ) )

ii. Calcolo relazionale: {s.Nome | s ( S T A D I O ) | ->(3I(INCONTRO) (3«(NAZIONALE)

(¿.NomeStadio = ¿.Nome A «.Continente = 'Europa' A (¿.Squadrai = «.Paese v ¿.Squadra2 = « P a e s e ) ) ) ) }

iii. Datalog: STADi0C0NEuR0PEA(N0meStadÌ0 : «) L N C O N T R O ( N o m e S t a d i o : « , D a t a : d, O r a : o,

Squadrai : s u Squadra2 : s2), N A Z i O N A L E ( P a e s e : j i , C o n t i n e n t e : c, C a t e g o r i a : et),

c = 'Europa' STADi0C0NEuR0PEA(N0meStadÌ0 : «) L N C O N T R O ( N o m e S t a d i o : n, D a t a : d. O r a : o, S q u a d r a i : s\, S q u a d r a 2 : s2), N A Z I O N A L E ( P a e s e : s2, C o n t i n e n t e : c. C a t e g o r i a : et),

c = 'Europa'

(c) Estrarre la capienza complessiva degli stadi in cui si giocano le partite che hanno come prima squadra una nazione sudamericana (nota: ai fini della valutazione della capienza complessiva, si sommino le capienze associate a ciascuna gara, anche se più gare si svolgono nello stesso stadio). Soluzione: select sum(Capienza) f r o m S t a d i o j o i n I n c o n t r o o n Nome where Squadrai in select Paese from Nazionale where

Continente

=

NomeStadio

=

'Sudamerica'

2. Dato il seguente schema relazionale: MOTO(Targa,Cilindrata, Marca, Nazione,Tasse) PRQPRiETARio(Nome,Targa)

Scrivere in SQL le interrogazioni seguenti: (a) Estrarre i nomi dei proprietari di solo moto giapponesi di almeno due marche diverse. i. Prima soluzione: select Nome from P r o p r i e t a r i o j o i n Moto on Proprietario.Targa=Moto.Targa w h e r e Nome n o t in (select Nome from P r o p r i e t a r i o j o i n Moto on Proprietario.Targa=Moto.Targa w h e r e N a z i o n e 'Giappone') g r o u p b y Nome h a v i n g c o u n t ( d i s t i n c t M a r c a ) >= 2

ii. Seconda soluzione: select PI.Nome from Proprietario Proprietario where Pi.Nome not

PI, P2, in

Moto Moto

MI, M2

(select Nome from P r o p r i e t a r i o j o i n Moto on Proprietario.Targa=Moto.Targa w h e r e N a z i o n e ' G i a p p o n e ' ) and PI.Targa = Mi.Targa and P2.Targa = M2.Targa and Pi.Nome = P2.Nome and M i . M a r c a < > M2 . M a r c a

(b) Rappresentare la query in algebra relazionale. Soluzione: 7TNOME( ( P R O P R I E T A R I O

MMOTO)

txI Marca ? iMarca2ANome=Nome2

(PNome2-Nome(PROPRIETARIO) X p M a r c a 2 _ M a r c a ( M O T O ) ) ) -

TTNome (PROPRIETARIO M a Nazione^ •Giappone' M O T O )

Note bibliografiche SQL è stato inizialmente descritto da Chamberlin et al. in [19] e [20]. Studi sistematici del linguaggio SQL, relativamente alle tecniche di ottimizzazione e al significato delle query, sono contenuti in [16] e [41]. La descrizione ufficiale dello standard SQL può essere ottenuta dall'Organizzazione internazionale degli standard ISO. Tali documenti sono però di costo elevato e di lettura non molto agevole. Su SQL esistono un gran numero di libri, tra i quali il libro di Cannan e Otten [12] (di cui esiste la traduzione italiana) e il libro di Melton e Simon [48]. Eisemberg e Melton [31] discutono il processo di standardizzazione in generale e con riferimenti specifici all'area delle basi di dati. Melton e Simon [49] presentano le principali caratteristiche di SQL-3. Spesso i manuali che accompagnano i sistemi relazionali commerciali sono fatti con molta cura e possono costituire un ottimo punto di riferimento. Tra l'altro questi manuali sono indispensabili per conoscere quali funzionalità di SQL sono state effettivamente implementate nel particolare sistema.

Soluzioni sul sito

http: //www. ateneonline. it/atzeni

Esercizi 4.1 Ordinare i seguenti domini in base al valore massimo rappresentabile, supponendo che integer abbia una rappresentazione a 32 bit e smallint a 16 bit: numeric (12,4), decimai (10), decimai (9), integer, smallint, decimai

(6,1). 4.2

Definire un attributo che permetta di rappresentare stringhe di lunghezza massima pari a 256 caratteri, su cui non sono ammessi valori nulli e con valore di default "sconosciuto".

4.3 Dare le definizioni SQL delle tre tabelle FQNDlSTA(Nome, Nazione, Età), GAREGGIA(NomeFondista, NomeGara, Piazzamento) e GARA(Nome, Luogo, Nazione, Lunghezza), rappresentando in particolare i vincoli di foreign key della tabella GAREGGIA. 4.4 Dare le definizioni SQL delle tabelle AUTQRE(Nome,Cognome, DataNascita, Nazionalità), LIBROfTitoloLibro, NomeAutore, CognomeAutore, Lingua). Per il vincolo di foreign key specificare una politica di cascade sulle cancellazione e di set nuli sulle modifiche.

4.5 Dato lo schema dell'esercizio precedente, spiegare cosa può capitare con l'esecuzione dei seguenti comandi di aggiornamento:

delete from Autore where Cognome = 'Rossi' update Libro set Nome = 'Umberto' where Cognome = 'Eco' insert into Autore(Nome,Cognome) values('Antonio','Bianchi') update Autore set Nome = 'Italo' where Cognome = 'Calvino'

4.6 Date le definizioni:

create domain Dominio integer default 10 create table Tabella(Attributo Dominio default 5) indicare cosa avviene in seguito ai comandi:

alter table Tabella alter column Attributo drop default alter domain Dominio drop default drop domain Dominio

4.7 Con riferimento a una relazione PROFESSORI(CF, Nome, Età, Qualifica), scrivere le interrogazioni SQL che calcolano l'età media dei professori di ciascuna qualifica, nei due casi seguenti: 1. se l'età non è nota si usa per essa il valore nullo 2. se l'età non è nota si usa per essa il valore 0 4.8

Spiegare perché in SQL è previsto (e necessario) un operatore di unione mentre in molte versioni non esistono gli operatori di intersezione e differenza.

4.9

Considerare le relazioni IMPIEGATI (Matricola, Nome, Stipendio, Direttore) e DIPARTIMENTI (Codice, Direttore) e le due interrogazioni seguenti, specificare se e in quali casi esse possono produrre risultati diversi: select avg(Stipendio) from Impiegato where Direttore in (select Direttore from Dipartimento) select avg(Stipendio) from Impiegato I, Dipartimento D where I.Direttore = D.Direttore

4.10 Si consideri una base di dati sulle relazioni

Ri(A- B. C) R2(D,E, F) Facendo riferimento a una versione delI'SQL che non prevede la differenza (parole chiave EXCEPT e MINUS) e che permette l'uso dei confronti nella nidificazione solo su singoli attributi (e quindi non ammette condizioni del tipo ... (A,B) IN SELECT C,D FROM ... ), scrivere interrogazioni in SQL equivalenti alle seguenti espressioni dell'algebra relazionale:

7T B(RXMc=Dcr ^

AB(R\)-71

f=2

(R2)) AB(RXMC=DR2))

4.11 Con riferimento alla base di dati nell'Esercizio 4.10 scrivere espressioni dell'algebra relazionale equivalenti alle seguenti interrogazioni SQL: 1. select distinct A , B from RI, R2 where C = D and E > 100 2. select distinct A , B from RI XI where not exists (select * from RI Yl, R2 where Yl.C = D and XI.A = Yl.A and F>10) 4.12 Con riferimento alla base di dati nell'Esercizio 4.10, indicare, per ciascuna delle seguenti interrogazioni, se la parola chiave distinct è necessaria. 1. l'interrogazione 1 nell'Esercizio 4.11 2. l'interrogazione 2 nell'Esercizio 4.11 3. select distinct A , B from RI, R2 where B = D and C = E 4. select distinct B , C from RI, R2 where B = D and C = E 4.13 Con riferimento a una base di dati sullo schema #i(A,B,C), /?2(A,B,C),/?3(C,D,E) considerare l'espressione dell'algebra relazionale TC A e ( ( R \ URI) M/?3) e scrivere un'espressione SQL a essa equivalente senza utilizzare il join esplicito (cioè la parola chiave JOIN) né viste. 4.14 Dato il seguente schema: AEROPORTO(Città, Nazione, NumPiste) VOLO(ldVolo,GiornoSett,CittaPart,OraPart,CittaArr,OraArr,TipoAereo) AEREO(TipoAereo,NumPasseggeri,QtaMerci) scrivere le interrogazioni SQL che permettono di determinare:

1. 2. 3. 4. 5. 6. 7. 8. 9. 10.

11.

le città con un aeroporto di cui non è noto il numero di piste; le nazioni da cui parte e arriva il volo con codice AZ274; i tipi di aereo usati nei voli che partono da Torino; i tipi di aereo e il corrispondente numero di passeggeri per i tipi di aereo usati nei voli che partono da Torino. Se la descrizione dell'aereo non è disponibile, visualizzare solamente il tipo; le città da cui partono voli internazionali; le città da cui partono voli diretti a Bologna, ordinate alfabeticamente; il numero di voli internazionali che partono il giovedì da Napoli; il numero di voli internazionali che partono ogni settimana da città italiane (farlo in due modi, facendo comparire o meno nel risultato gli aeroporti senza voli internazionali); le città francesi da cui partono più di venti voli alla settimana diretti in Italia; gli aeroporti italiani che hanno solo voli interni. Rappresentare questa interrogazione in quattro modi: (i) con operatori insiemistici, (ii) con un'interrogazione nidificata con l'operatore not in, (iii) con un'interrogazione nidificata con l'operatore not exists, (iv) con l'outer join e l'operatore di conteggio. Esprimere l'interrogazione pure in algebra relazionale; le città che sono servite dall'aereo caratterizzato dal massimo numero di passeggeri.

4.15 Dato il seguente schema:

DISCO(NroSerie,TitoloAlbum, Anno,Prezzo) CONTIENE(NroSerieDisco,CodiceReq,NroProqr) ESECUZIONE(CodiceReq, TitoloCanz,Anno) AUTORE(Nome,TitoloCanzone) CANTANTE(NomeCantante,CodiceReq)

formulare le interrogazioni SQL che permettono di determinare: 1. i cantautori (persone che hanno scritto e cantato la stessa canzone) il cui nome inizia per 'D'; 2. i titoli dei dischi che contengono canzoni di cui non si conosce l'anno di registrazione; 3. i pezzi del disco con numero di serie 78574, ordinati per numero progressivo, con indicazione degli interpreti per i pezzi che hanno associato un cantante; 4. gli autori e i cantanti puri, ovvero autori che non hanno mai registrato una canzone e cantanti che non hanno mai scritto una canzone; 5. i cantanti del disco che contiene il maggior numero di canzoni; 6. gli autori solisti di "collezioni di successi" (dischi in cui tutte le canzoni sono di un solo cantante e in cui almeno tre registrazioni sono di anni precedenti la pubblicazione del disco); 7. i cantanti che non hanno mai registrato una canzone come solisti; 8. i cantanti che non hanno mai inciso un disco in cui comparissero come unici cantanti; 9. i cantanti che hanno sempre registrato canzoni come solisti. 4.16 Considerare la base di dati relazionale definita per mezzo delle seguenti istruzioni:

create table Studenti ( Matricola numeric not nuli primary key, Cognome char(20) not nuli, Nome char(20) not nuli, DataNascita date not nuli ) ; create table Esami ( CodiceCorso numeric not nuli, studente numeric not nuli references Studenti(matricola), data date not nuli, voto numeric not nuli, primary key (CodiceCorso, studente, data) ) ; Si supponga che vengano registrati anche gli esami non superati, con voti inferiori al 18. Formulare in SQL: 1. l'interrogazione che trova gli studenti che non hanno superato esami; 2. l'interrogazione che trova gli studenti che hanno riportato in almeno un esame un voto più alto di Archimede Pitagorico; 3. l'interrogazione che trova i nomi degli studenti che hanno superato almeno due esami; 4. l'interrogazione che trova, per ogni studente, il numero di esami superati e la relativa media; 4.17 Considerare la seguente base di dati relazionale: NEGOZI(IDNegozio, Nome, Città) PRODOTTI(CodProdotto, NomeProdotto, Marca) LISTINO(Negozio, Prodotto, Prezzo) con vincoli di integrità referenziale fra Negozio e la relazione NEGOZI fra Prodotto e la relazione PRODOTTI. Fare riferimento a una versione delI'SQL che non prevede la differenza (parole chiave except e minus) e che permette l'uso dei confronti nella nidificazione solo su singoli attributi (quindi sono ammesse condizioni del tipo ... A in s e l e c t C from ... ma non del tipo ... (A,B) in select C, D from ... • Formulare in SQL l'interrogazione che fornisce nome e città dei negozi che vendono prodotti della marca XYZ • Formulare in SQL l'interrogazione che trova, per ciascun prodotto, la città in cui viene venduto al prezzo più basso • Formulare in SQL l'interrogazione che trova i prodotti che vengono venduti in una sola città. 4.18 Dare una sequenza di comandi di aggiornamento che modifichi l'attributo Stipendio della tabella IMPIEGATO, aumentando del 10% gli stipendi sotto i 30 mila euro e diminuendo del 5% gli stipendi sopra i 30 mila euro.

SQL: caratteristiche evolute

Il capitolo continua la presentazione delle caratteristiche del linguaggio SQL, mostrando alcune caratteristiche evolute del linguaggio. Completeremo la descrizione dei servizi per la definizione dei dati, mostrando l'uso del linguaggio di interrogazione in questo contesto (Paragrafo 5.1). Illustreremo poi l'uso di funzioni scalari (Paragrafo 5.2) e i comandi per il controllo dell'accesso ai dati (Paragrafo 5.3). Infine, descriveremo le caratteristiche di base dei comandi SQL per la gestione delle transazioni (Paragrafo 5.4).

5.1 Caratteristiche evolute di definizione dei dati Dopo aver descritto nel capitolo precedente i comandi di base per la definizione dei dati e la scrittura delle interrogazioni in SQL, completiamo ora la rassegna dei componenti di uno schema. Descriviamo quindi la clausola c h e c k , le asserzioni e le primitive per la definizione di viste.

5.1.1 Vincoli di integrità generici Abbiamo visto che SQL permette di specificare un certo insieme di vincoli sugli attributi e sulle tabelle, soddisfacendo le più importanti esigenze, ma senza esaurire i bisogni delle applicazioni. Per specificare ulteriori vincoli, SQL-2 ha introdotto la clausola c h e c k , con la seguente sintassi: check

( Condizione )

Le condizioni che si possono usare sono quelle che possono apparire come argomento della clausola w h e r e di una interrogazione SQL. La condizione deve essere sempre verificata affinché la base di dati sia corretta. In questo modo è possibile specificare tutti i vincoli intrarelazionali descritti nel Paragrafo 4.2.6, e anche di più, poiché la condizione può far riferimento ad altri attributi. Una efficace dimostrazione della potenza del costrutto consiste nel far vedere come i vincoli predefiniti possano tutti essere descritti con la clausola c h e c k . Per questo possiamo prendere la definizione dello schema della tabella I M P I E G A T O che è stata data nel Paragrafo 4.2.7 (la prima delle tre):

create table Impiegato (Matricola character(6) check (Matricola is not nuli and 1 = (select count(*) from Impiegato I where Matricola=I.Matric Cognome character(20) check (Cognome i s n o t Nome character(20) check (Nome i s n o t n u l 2 > (select count(*) from Impiegato I w h e r e Nome = I . N o m e and Cognome = I.Cognome) Dipart character(15) check (Dipart in (select NomeDip from Dipartimento))

ola)), nuli), i and

),

) Confrontando questa specifica con quella che faceva uso dei vincoli predefiniti, possiamo fare diverse osservazioni. In primo luogo, i vincoli predefiniti permettono una rappresentazione molto più compatta e leggibile; per esempio il vincolo di chiave ha bisogno di una rappresentazione abbastanza complicata, che fa uso dell'operatore aggregato c o u n t . Si nota anche che utilizzando la clausola c h e c k si perde la possibilità di associare ai vincoli una politica di reazione alle violazioni. Infine, quando i vincoli sono definiti mediante i costrutti predefiniti, il sistema li può riconoscere immediatamente e spesso può riuscire a gestirli in modo più efficiente. Per apprezzare il potere espressivo di questo costrutto si può per esempio descrivere un vincolo che obbliga l'impiegato ad avere un manager del proprio dipartimento, a meno che la matricola non inizi con la cifra 1. Si estende la precedente definizione di tabella con le seguenti dichiarazioni: Superiore check

character(6),

(Matricola Dipart

=

like

"1%"

(select from where

or

Dipart

Impiegato

I

I.Matricola

=

Superiore))

5.1.2 Asserzioni Grazie alla clausola c h e c k è possibile definire anche un ulteriore componente dello schema di una base di dati, le asserzioni. Le asserzioni, introdotte in SQL-2, rappresentano dei vincoli che non sono associati a nessun attributo o tabella in particolare, bensì appartengono direttamente allo schema. Mediante le asserzioni è possibile esprimere tutti i vincoli che abbiamo prima specificato nell'ambito della definizione delle tabelle. Le asserzioni permettono poi di esprimere vincoli che non sarebbero altrimenti definibili, come vincoli su

più tabelle o vincoli che richiedono che una tabella abbia una cardinalità minim a . L e a s s e r z i o n i p o s s i e d o n o u n n o m e , t r a m i t e il q u a l e p o s s o n o e s s e r e e l i m i n a t e esplicitamente dallo schema con l'istruzione d r o p (Paragrafo 4.2.8). L a s i n t a s s i p e r la d e f i n i z i o n e d e l l e a s s e r z i o n i è:

create

a s s e r t i o n Nome Asserzione

c h e c k (Condizione)

U n ' a s s e r z i o n e p u ò p e r e s e m p i o i m p o r r e c h e in IMPIEGATO sia s e m p r e p r e s e n t e a l m e n o u n a riga: create

assertion AlmenoUnlmpiegato check ( 1 10

Costruiamo quindi una vista I M P I E G A T I A M M I N P O V E R I definita a partire dalla vista I M P I E G A T I A M M I N , che conterrà gli impiegati amministrativi con uno stipendio compreso tra i 10 e i 50 mila euro:

create view ImpiegatiAmminPoveri as select * from where with

ImpiegatiAmmin S t i p e n d i o check


1975;

2.58 * (22.00

KWatt + 1.00

*

KWatt)

La seconda forma del costrutto c a s e invece ammette la valutazione di predicati SQL generici. Mostriamo un esempio di applicazione di questa forma nel contesto di un'operazione di aggiornamento. La seguente istruzione SQL specifica una modifica dello stipendio di un impiegato, sulla base dei valori assunti dalle colonne Dipart e Ufficio. update Impiegato set Stipendio = case when (Dipart = th when th when th else end

'Amministrazione'

en Stipendio * 1.1 (Dipart = 'Amministrazione' en Stipendio * 1.2 Dipart = 'Produzione' en Stipendio * 1.15 Stipendio

and

Ufficio

=

and

Ufficio

10) 10)

Se non si facesse uso della funzione c a s e , non sarebbe possibile effettuare la medesima operazione con una sola istruzione.

5.3 Controllo dell'accesso La presenza di meccanismi di protezione dei dati riveste grande rilevanza in molte applicazioni. Uno dei compiti più importanti di un amministratore di basi di dati consiste nello scegliere e implementare opportune politiche di controllo di accesso. SQL riconosce l'importanza di questo aspetto e un insieme delle istruzioni del linguaggio è dedicato a questo obiettivo. SQL prevede innanzitutto che ogni utente sia identificato in modo univoco dal sistema. L'identificazione dell'utente può sfruttare le funzionalità del sistema

operativo (per cui a un utente della base di dati corrisponde un utente del sistema) o essere indipendente. I sistemi commerciali più sofisticati offrono una gestione indipendente, con una propria procedura d'identificazione, per cui a un utente del sistema possono corrispondere più utenti della base di dati e viceversa.

5.3.1 Risorse e privilegi Le risorse che il sistema protegge sono normalmente tabelle e viste, con la possibilità di specificare singoli attributi all'interno di esse. Il modello di controllo dell'accesso di SQL permette comunque di proteggere un qualsiasi componente dello schema (domini, procedure ecc.). Di regola l'utente che crea la risorsa ne è il proprietario ed è autorizzato a compiere su di essa qualsiasi operazione. Un sistema in cui solo i proprietari delle risorse fossero autorizzati a farne uso sarebbe di limitata utilità, come lo sarebbe un sistema in cui tutti gli utenti fossero in grado di utilizzare in qualsiasi modo ogni risorsa. SQL offre invece dei meccanismi di gestione flessibili, mediante i quali è possibile specificare quali sono le risorse cui devono accedere gli utenti e quali sono invece le risorse che devono essere mantenute private. Il sistema basa il controllo di accesso su un concetto di privilegio. Gli utenti possiedono dei privilegi di accesso alle risorse del sistema. Ogni privilegio è caratterizzato dai seguenti parametri: 1. 2. 3. 4. 5.

la risorsa cui si riferisce; l'utente che concede il privilegio; l'utente che riceve il privilegio; l'azione che viene permessa sulla risorsa; se il privilegio può essere trasmesso o meno ad altri utenti.

Quando una risorsa viene creata, il sistema concede automaticamente tutti i privilegi su tale risorsa al creatore. Esiste inoltre un utente predefinito, . s y s t e m , che rappresenta il database administrator, il quale possiede tutti i privilegi su tutte le risorse. I privilegi disponibili sono i seguenti. • i n s e r t : permette di inserire un nuovo oggetto nella risorsa (si può applicare solo alle tabelle e alle viste). • u p d a t e : permette di aggiornare il valore di un oggetto (vale per le tabelle, le viste e gli attributi). • d e l e t e : permette di rimuovere oggetti dalla risorsa (vale solo per le tabelle e le viste). • s e l e c t : permette di leggere la risorsa, ovvero utilizzarla nell'ambito di una interrogazione (vale per le tabelle, le viste e gli attributi). • r e f e r e n c e s : permette che venga fatto un riferimento a una risorsa nell'ambito della definizione dello schema di una tabella. Può essere associato solo a tabelle e a specifici attributi. Con il privilegio di r e f e r e n c e s (per esempio su una tabella D I P A R T I M E N T O , di proprietà di Paolo) l'utente cui è concesso il privilegio (per esempio, Stefano) può definire un vincolo di f o r e i g n k e y

(per esempio, sulla sua tabella IMPIEGATO), richiedendo che un attributo della propria tabella abbia valori contenuti tra le chiavi della tabella referenziata. A questo punto, se Stefano specifica sul vincolo una politica di reazione di tipo n o a c t i o n , a Paolo può essere impedito di cancellare o modificare delle righe della propria tabella D I P A R T I M E N T O se il comando di aggiornamento rende scorretto il contenuto di I M P I E G A T O . Perciò, la concessione del privilegio di r e f e r e n c e s può limitare la possibilità di modificare la risorsa. • u s a g e : permette che venga usata la risorsa, per esempio nell'ambito della definizione dello schema di una tabella, ma solo per risorse come i domini. 11 privilegio di effettuare un d r o p o un a l t e r di un oggetto non può essere concesso, ma rimane di competenza del creatore dell'oggetto stesso. I privilegi vengono concessi o revocati tramite le istruzioni g r a n t e r e v o k e .

5.3.2 Comandi per concedere e revocare privilegi La sintassi del comando g r a n t è la seguente: g r a n t Privilegi

o n Risorsa

t o Utenti

[with

g r a n t

o p t i o n ]

11 comando permette di concedere i Privilegi sulla Risorsa agli Utenti. Per esempio, il comando: g r a n t

s e l e c t

on

Dipartimento

to

Stefano

concede all'utente Stefano il privilegio di s e l e c t sulla tabella D I P A R T I M E N T O . La clausola w i t h g r a n t o p t i o n specifica se deve essere concesso a Stefano anche il privilegio di propagare il privilegio ad altri utenti. È possibile usare al posto dei privilegi la parola chiave a l i p r i v i l e g e s , che identifica tutti i privilegi che l'utente può concedere sulla particolare risorsa. Così il comando: g r a n t

a l i

p r i v i l e g e s

on

Impiegato

to

Paolo,

Riccardo

concede sulla tabella I M P I E G A T O agli utenti Paolo e Riccardo tutti i privilegi che possono essere concessi da chi esegue il comando. Il comando r e v o k e fa invece l'inverso: sottrae a un utente i privilegi che gli erano stati concessi: r e v o k e Privilegi

o n Risorsa

f r o m Utenti [ r e s t r i c t | c a s c a d e ]

Tra i privilegi che possono essere rimossi, oltre a quelli che possono comparire come argomento del comando di g r a n t , vi è pure il privilegio g r a n t o p t i o n , derivante dall'uso dell'opzione w i t h g r a n t o p t i o n . L unico utente che può sottrarre privilegi a un altro utente è l'utente che aveva concesso i privilegi in primo luogo. 11 comando di r e v o k e può eliminare tutti i privilegi che erano stati concessi, o limitarsi a revocarne un sottoinsieme. L'opzione r e s t r i c t è il valore di default e specifica che il comando non deve essere

eseguito qualora la revoca dei privilegi all'utente comporti qualche altra revoca di privilegi, come può capitare quando l'utente ha ricevuto i privilegi con la g r a n t option e ha propagato il privilegio ad altri utenti, o come capita quando il privilegio che si vuole revocare è stato usato per la definizione di una vista o di una tabella dell'utente. Con l'opzione r e s t r i c t in una situazione di questo tipo viene segnalato un errore. Con l'opzione di c a s c a d e , invece, si forza l'esecuzione del comando; così tutti i privilegi che erano stati propagati vengono revocati e tutti gli elementi della base di dati che erano stati costruiti sfruttando questi privilegi vengono rimossi. Si noti che l'opzione c a s c a d e può generare anche in questo caso una reazione a catena, per cui, per ogni elemento che viene rimosso, vengono anche rimossi tutti gli oggetti che hanno una qualche relazione di dipendenza da esso; come in altri casi bisogna prestare molta attenzione per evitare che un semplice comando produca modifiche estese e non desiderate sulla base di dati. Non è solo il comando di r e v o k e a poter generare delle reazioni a catena: anche quello di g r a n t può esibire un comportamento analogo. Può infatti capitare che un utente abbia ricevuto un privilegio su una tabella che gli ha permesso di creare delle viste che fanno riferimento a questa tabella, tramite per esempio un privilegio di s e l e c t . Qualora all'utente vengano concessi ulteriori privilegi sulla tabella, questi privilegi vengono automaticamente concessi sulle viste (e ricorsivamente sulle viste costruite a partire dalle viste).

5.3.3 I ruoli in SQL-3 SQL-3 ha introdotto una novità significativa nell'ambito del controllo dell'accesso, proponendo un modello di controllo dell'accesso basato sui ruoli (Role-Based Access Control, RBAC). Questo modello, pur mantenendo il supporto per il tradizionale approccio che associa direttamente i privilegi agli utenti, introduce un meccanismo che disaccoppia l'attribuzione di un insieme di privilegi agli utenti dalla loro attivazione. In SQL-3 è possibile creare un ruolo tramite un opportuno comando c r e a t e r o l e NomeRuolo. 11 ruolo si comporta come una sorta di contenitore di privilegi, che vengono attribuiti a esso tramite il comando di g r a n t visto prima. Il comando di g r a n t viene inoltre utilizzato per concedere agli utenti la possibilità di ricoprire un certo ruolo, beneficiando dei privilegi a esso associati. Per fruire però dei privilegi è necessario che l'utente invochi un esplicito comando s e t r o l e NomeRuolo. In ogni istante un utente dispone quindi dei privilegi che gli sono stati attribuiti direttamente e dei privilegi associati al ruolo che è stato esplicitamente attivato. Questo approccio rappresenta una realizzazione significativa di un modello di controllo dell'accesso flessibile. La motivazione principale del modello è di rispettare il principio del "minimo privilegio", il quale prescrive che per garantire un buon comportamento in termini di sicurezza è bene che ogni utente disponga esclusivamente dell'insieme dei privilegi che sono necessari per svolgere il proprio compito. Questo principio motiva innanzitutto l'introduzione di un modello di controllo dell'accesso a granularità fine come quello tradizionale di SQL, che

permette di isolare le risorse effettive cui un utente ha diritto di accedere. 11 modello a ruoli tiene inoltre conto che ciascun utente ha in momenti diversi la necessità di svolgere diverse funzioni; tramite il ruolo diventa possibile variare dinamicamente l'insieme di privilegi attivati, disponendo in ogni momento dell'insieme minimo di privilegi necessari per una certa attività. Un altro vantaggio significativo dei ruoli è la semplificazione dell'attività di amministrazione dei privilegi. L'introduzione di un nuovo utente nel sistema può essere gestita abilitando con pochi comandi i ruoli che l'utente deve poter attivare, senza dover ripetere per il nuovo identificatore di utente tutti i comandi di g r a n t che descrivono la collezione di privilegi raccolti nei ruoli.

5.4 Transazioni Introduciamo ora la nozione di transazione, un concetto che riveste un ruolo fondamentale nell'uso delle basi di dati. Una transazione identifica una unità elementare di lavoro svolta da una applicazione, cui si vogliono associare particolari caratteristiche di correttezza, robustezza e isolamento. Un sistema che mette a disposizione un meccanismo per la definizione e l'esecuzione di transazioni viene detto sistema transazionale. Una transazione può essere definita sintatticamente: in SQL, l'inizio di una transazione è rappresentato dal comando s t a r t t r a n s a c t i o n . 11 termine della transazione è rappresentato da due istruzioni particolari, c o m m i t w o r k e r o l l b a c k w o r k , cui facciamo riferimento usando i due termini commit e abort, che indicano l'azione associata alla rispettiva istruzione (in effetti, la sintassi SQL ammette anche i comandi nella forma senza il termine w o r k ) . L'effetto di questi due comandi è decisivo per l'esito della transazione, la quale "va a buon fine" solo a seguito di un commit, mentre non ha alcun effetto tangibile sulla base di dati quando viene eseguito l'abort. Dal punto di vista del potere espressivo, si noti che l'istruzione r o l l b a c k w o r k è molto potente, in quanto tramite essa l'utente della base di dati può annullare gli effetti del lavoro svolto dalla transazione, indipendentemente dalla sua complessità. Un esempio di transazione è dato dal seguente codice, che trasferisce dal conto 42177 al conto 12202 l'ammontare 10. s t a r t update

transaction; ContoCorrente

s e t Ammontare = Ammontare where NumConto = 12202; update ContoCorrente

+

10

s e t Ammontare = Ammontare where NumConto = 42177; commit work;

-

10

V i e n e d e t t a ben formata una t r a n s a z i o n e iniziata d a s t a r t t r a n s a c t i o n nel c o r s o della cui e s e c u z i o n e viene invocato u n o solo dei d u e c o m a n d i c o m m i t

w o r k o rollback work. In alcune interfacce transazionali, viene immediatamente e implicitamente eseguito dopo ogni commit o abort un comando s t a r t transaction, in modo da rendere tutte le computazioni transazioni ben formate. In tal caso start t r a n s a c t i o n diventa opzionale o addirittura non è previsto. Tutto il codice che viene eseguito all'interno di una transazione gode di proprietà particolari, le cosiddette proprietà acide delle transazioni: atomicità, consistenza, isolamento e persistenza (il termine è un acronimo derivante dall'inglese, ove ACID denota le iniziali di: "Atomicity, Consistency, Isolation, Durability"). Atomicità Vatomicità rappresenta il fatto che una transazione è un'unità indivisibile di esecuzione; o vengono resi visibili tutti gli effetti di una transazione, oppure la transazione non deve avere alcun effetto sulla base di dati, con un approccio "tutto o niente". In pratica, non è possibile lasciare la base di dati in uno stato intermedio attraversato durante l'elaborazione della transazione. L'atomicità ha conseguenze significative sul piano operativo. Se durante l'esecuzione delle operazioni si verifica un errore e una delle operazioni di lettura o modifica della base di dati non può essere portata a compimento, allora il sistema deve essere in grado di ricostruire la situazione esistente all'inizio della transazione, disfacendo il lavoro svolto dalle istruzioni eseguite fino a quel momento (operazione di u n d o ) . Viceversa, dopo l'esecuzione del commit, il sistema deve assicurare che la transazione lasci la base di dati nel suo stato finale; ciò può comportare di dover rifare il lavoro svolto (operazione di r e d o ) . In questo modo, la corretta effettuazione dell'operazione di commit fissa il momento, atomico e indivisibile, in cui la transazione "va a buon fine"; prima di tale operazione, qualunque guasto provoca la eliminazione di tutti gli effetti della transazione, che ripristina lo stato iniziale. Quando viene eseguito il comando r o l l b a c k w o r k , la situazione è simile a un "suicidio" autonomamente deciso nell'ambito della transazione. Viceversa, il sistema può decidere che la transazione non può essere portata a corretto compimento e "uccidere" la transazione. Infine, varie transazioni possono essere "uccise" a seguito di un guasto del sistema. In entrambe le situazioni (suicidio od omicidio), i meccanismi che realizzano l'abort di una transazione utilizzano le stesse strutture dati e talvolta gli stessi algoritmi. In genere, ci aspettiamo che le applicazioni siano scritte bene e che perciò la maggioranza delle transazioni vadano a buon fine e terminino con un commit; solo in casi sporadici legati a malfunzionamenti o situazioni impreviste le transazioni terminano con un abort.

Consistenza

L a consistenza richiede che l'esecuzione della transazione non violi i vincoli di integrità definiti sulla base di dati. Quando il sistema rileva che una transazione sta violando uno dei vincoli, per esempio che si sta inserendo una tupla con un campo chiave avente un valore già presente nella tabella, il sistema interviene per annullare la transazione o per correggere la violazione del vincolo. La verifica di vincoli di integrità di tipo immediato può essere fatta nel corso della transazione, rimuovendo gli effetti della specifica istruzione di manipolazione dei

dati che causa la violazione del vincolo, senza imporre un abort alle transazioni. Invece, la verifica di vincoli di integrità di tipo differito deve essere effettuata alla conclusione della transazione, dopo che l'utente ha richiesto il commit. Si noti che in questo secondo caso, se il vincolo è violato, l'istruzione c o m m i t w o r k non va a buon fine, e gli effetti della transazione vengono annullati "in extremis", cioè poco prima di produrre e rendere visibile lo stato finale della base di dati, poiché questo stato sarebbe inconsistente. Isolamento L'isolamento richiede che l'esecuzione di una transazione sia indipendente dalla contemporanea esecuzione di altre transazioni. In particolare, si richiede che il risultato dell'esecuzione concorrente di un insieme di transazioni sia analogo al risultato che le stesse transazioni otterrebbero qualora ciascuna di esse fosse eseguita da sola. L'isolamento si pone come obiettivo anche di rendere l'esito di ciascuna transazione indipendente da tutte le altre; si vuole cioè impedire che l'esecuzione di un rollback di una transazione causi l'esecuzione del rollback di altre transazioni, eventualmente generando una reazione a catena (effetto domino). Persistenza La persistenza invece richiede che l'effetto di una transazione che ha eseguito il commit correttamente non venga più perso. In pratica, una base di dati deve garantire che nessun dato venga perso per nessun motivo; si pensi al valore dell'informazione contenuta in una base di dati quando essa rappresenta un'operazione su un conto corrente bancario. Concludendo, si noti che la definizione di transazione data in questo paragrafo è diversa dal concetto di transazione che può avere un utente. Per il sistema, una transazione è una unità di esecuzione caratterizzata da proprietà acide; per l'utente, una transazione è spesso identificata con ogni interazione col sistema, caratterizzata da una iniziale immissione di dati cui fa seguito una risposta da parte del sistema. Spesso le due nozioni coincidono, ma altre volte una transazione di sistema incapsula varie transazioni d'utente, oppure una transazione d'utente incapsula varie transazioni di sistema.

Note bibliografiche Per quanto riguarda le caratteristiche evolute di SQL, valgono gli stessi riferimenti che sono stati forniti nel capitolo precedente. Anche in questo caso si può consigliare di consultare i manuali che accompagnano i sistemi relazionali commerciali, i quali oggigiorno sono quasi sempre disponibili per la consultazione in Internet sui siti dei produttori, con funzioni di ricerca efficaci che consentono in breve tempo di risolvere dubbi sulla sintassi di un comando o sull'insieme di opzioni effettivamente riconosciute dall'interprete SQL di uno specifico sistema. Per quanto riguarda il controllo dell'accesso nelle basi di dati, il testo [13] è dedicato totalmente all'argomento. Per quanto riguarda il concetto di transazione, si fa riferimento al secondo volume [5], che costituisce il naturale proseguimento di questo testo.

Esercizi 5.1

Definire sulla tabella IMPIEGATO il vincolo che il dipartimento Amministrazione abbia meno di 100 dipendenti, con uno stipendio medio superiore ai 40 mila euro.

5.2

Definire (con una opportuna notazione) su una relazione PAGHE (Matricola, StipLordo, Ritenute, StipNetto, OK) un vincolo che imponga che il valore di OK è: • zero se StipNetto è pari alla differenza fra StipLordo e Ritenute • uno altrimenti.

5.3

Definire a livello di schema il vincolo che il massimo degli stipendi degli impiegati di dipartimenti con sede a Firenze sia minore dello stipendio di tutti gli impiegati del dipartimento Direzione.

5.4

Indicare quali delle seguenti affermazioni sono vere. 1. Nei sistemi relazionali le viste possono essere utili al fine di rendere più semplice la scrittura delle interrogazioni. 2. Nei sistemi relazionali le viste possono essere utili al fine di rendere più efficienti le interrogazioni. 3. Nei sistemi relazionali le viste introducono ridondanze.

5.5

Dato il seguente schema: AEROPQRTO(Città, Nazione, NumPiste) VOLO(ldVolo,GiornoSett,CittaPart,OraPart, Citta Arr, Ora Arr,Ti poAereo) AEREQ(TipoAereo,NumPasseggeri,QtaMerci) scrivere, facendo uso di una vista, l'interrogazione SQL che permette di determinare il massimo numero di passeggeri che possono arrivare in un aeroporto italiano dalla Francia di giovedì (se vi sono più voli, si devono sommare i passeggeri).

5.6

Definire una vista che mostra per ogni dipartimento il valore medio degli stipendi superiori alla media.

5.7

Dato il seguente schema relazionale: • DIPENDENTE(CodiceFiscale, Cognome, Nome) • PRQFESSQRE(CodiceFiscale, Qualifica, Anzianità,Facoltà) con vincolo di integrità referenziale tra CodiceFiscale e la relazione DIPENDENTE e fra Facoltà e la relazione FACOLTÀ • FACOLTÀ (Codice, Nome, Indirizzo) • COIÌSODISTUDIQ(Codice, Nome, Facoltà, Presidente) con vincolo di integrità referenziale tra Facoltà e la relazione FACOLTÀ a fra Presidente e la relazione PROFESSORE • COLLABORAZIQNE(CorsoDiStudio, Facoltà, Professore, Tipo ) con vincolo di integrità referenziale fra CorsodiStudio, Facoltà e la relazione CORSODISTUDIO e fra Professore e la relazione PROFESSORE • CORSO(Codjce, Materia, Docente, Semestre) con vincolo di integrità referenziale fra Materia e la relazione MATERIA e fra Docente e la relazione PROFESSORE

• M A T E R I A (Sigla, Nome) formulare le interrogazioni in SQL:

1. mostrare i professori, con codice fiscale, cognome, cognome, qualifica, anzianità e nome della eventuale facoltà di afferenza (per i professori che non afferiscono ad alcuna facoltà dovrà comparire il valore nullo); 2. trovare cognome e qualifica dei professori che afferiscono alla stessa facoltà di un professore chiamato Mario Bruni di qualifica "ordinario"; 3. trovare i codici delle facoltà cui non afferisce alcun professore con cognome Bruni e qualifica "ordinario". 5.8

Considerare la base di dati relazionale definita per mezzo delle seguenti istruzioni (è lo schema già visto nell'Esercizio 4.16): create table Studenti ( Matricola numeric not nuli primary key, Cognome char(20) not nul1, Nome char(20) not nuli, DataNascita date not nuli ) ; create table Esami ( CodiceCorso numeric not nuli, studente numeric not nuli references Studenti(matricola), data date not nuli, voto numeric not nuli, primary key (CodiceCorso, studente, data) )\ Formulare in SQL: 1. l'interrogazione che trova lo studente con la media più alta.

5.9

Considerare la seguente base di dati relazionale: VENDITE(N u meroScontri no, Data) CLFFINTI(Codice, Cognome, Età) DETTAGLIVENDITE(N u meroScontri no, Riga, Prodotto, Importo, Cliente) con valori nulli ammessi sull'attributo Cliente e con vincoli di integrità referenziale fra NumeroScontrino e la relazione VENDITE e fra Cliente e la relazione CLIENTI;

formulare in SQL: • l'interrogazione che restituisce i prodotti acquistati in ciascuna data (che mostra cioè le coppie < p,d > tali che il prodotto p è stato acquistato nella data d; • l'interrogazione che restituisce i prodotti che sono stati acquistati in due date diverse; • la vistaVENDITECONTOTALE(NumeroScontrino,Totale),che riporta, per ogni scontrino l'importo totale (ottenuto come somma degli importi dei prodotti riportati sullo scontrino). 5.10 Considerare la seguente base di dati relazionale: • PERSONE(FC, Cognome, Nome, Età • IMMOBILI(Codice, Via, NumeroCivico, Città, Valore

• PROPRlETÀ(Persona, Immobile, Percentuale) con vincolo di di integrità referenziale fra Immobile e la relazione PERSONE e fra Immobile e la relazione IMMOBILI Nota: l'attributo Percentuale indica la percentuale di proprietà. Definire in SQL: • la vista definita per mezzo della seguente espressione dell'algebra relazionale: Vista = Immobili Mcodice=immobHe Proprietà • l'interrogazione che fornisce codici fiscali, nome e cognome delle persone che posseggono un solo immobile e po posseggono a 100% • l'interrogazione che fornisce, per ciascuna persona, il codice fiscale, il nome, il cognome e il valore complessivo degli immobili di sua proprietà (dove il valore è la somma dei valori ciascuno pesato con la percentuale di proprietà: se Tizio possiede un immobile di valore 150 al 100% e uno di valore 200 al 50%, allora il valore complessivo sarà (150 x 100)/100 + (200 x 50)/100 = 250). 5.11 Tramite la definizione di una vista, permettere all'utente "Carlo" di accedere al contenuto di IMPIEGATO, escludendo l'attributo Stipendio. 5.12 Descrivere l'effetto delle seguenti istruzioni: quali autorizzazioni sono presenti dopo ciascuna istruzione? (Ciascuna linea è preceduta dal nome dell'utente che esegue il comando.) Stefano:

grant select on Tabella to Paolo, Riccardo with grant option Paolo: grant select on Tabella to Piero Riccardo: grant select on Tabella to Piero with grant option Stefano: revoke select on Tabella from Paolo cascade Piero: grant select on Tabella to Paolo Stefano: revoke select on tabella from Riccardo cascade

SQL per le applicazioni

L'accesso di gran lunga più tipico a una base di dati avviene attraverso applicazioni integrate nel sistema informativo. Il dialogo diretto con l'interprete SQL è riservato a pochi utenti esperti. L'uso di apposite applicazioni per accedere alle informazioni è giustificato da una serie di considerazioni. Molto spesso chi deve accedere alle informazioni non è direttamente un utente, ma un'applicazione non interattiva (detta anche batch). Anche nel caso di accessi interattivi, spesso le modalità di accesso sono semplici e prevedibili; è quindi utile ridurre la complessità nell'accesso alla base di dati costruendo un'applicazione che fornisca un'interfaccia semplificata per lo svolgimento del compito. SQL viene incontro alle esigenze di costruzione delle applicazioni in due direzioni. La prima direzione è legata a un incremento delle funzionalità di SQL e in generale del DBMS. Il linguaggio SQL non si limita infatti alla definizione di semplici query o comandi di modifica, ma permette la definizione di componenti più estese, quali le procedure e i trigger. Tramite queste funzionalità è possibile aggregare diverse azioni SQL ed estendere l'insieme di servizi del sistema; in generale, queste estensioni rendono SQL analogo a un normale linguaggio di programmazione, permettendo in alcuni casi di realizzare completamente l'applicazione all'interno della base di dati. In questo capitolo presenteremo quindi l'estensione di SQL che permette la definizione di procedure (Paragrafo 6.1) e trigger (Paragrafo 6.2). Una evoluzione ulteriore in questa direzione è rappresentata da strumenti di sviluppo che permettono di costruire applicazioni complete per la gestione di basi di dati in modo guidato. Buona parte dei sistemi di basi di dati commerciali offrono, oltre al gestore di base di dati vero e proprio, anche un insieme di strumenti specializzati (e proprietari) per lo sviluppo di applicazioni (vedi per esempio la descrizione di Microsoft Access nell'Appendice A). Esiste poi un'offerta di prodotti non legati a una base di dati in particolare, ciascuno dei quali in grado di gestire il dialogo con il sistema relazionale grazie all'uso dello standard SQL. Questi strumenti permettono di definire agevolmente gli schemi della base di dati e di costruire interfacce sofisticate. Non tratteremo specificamente queste soluzioni, sia perché è la modalità relativamente meno diffusa, sia per la scarsa uniformità che rende difficile una trattazione sistematica. La seconda direzione invece assume che le applicazioni siano realizzate facendo uso dei tradizionali linguaggi di programmazione di alto livello. In questo caso, il problema da risolvere è relativo all'integrazione tra i comandi SQL, i quali sono responsabili di realizzare l'accesso alla base di dati, e le normali istruzioni del linguaggio di programmazione. La seconda parte del capitolo analizzerà il supporto richiesto per lo sviluppo di applicazioni nei linguaggi di programmazione di alto livello, di tipo procedurale e a oggetti; descriveremo prima SQL Embedded, in cui SQL viene integrato direttamente all'interno del normale linguaggio di programmazione (Paragrafo 6.3); illustreremo infine gli approcci in cui l'integrazione con SQL avviene tramite l'invocazione di un'opportuna libreria di funzioni (approccio a Cali Level Interface, Paragrafo 6.4).

Vogliamo infine osservare che la trattazione di questi argomenti in questo testo è volutamente sintetica. Maggiori approfondimenti sui trigger si trovano nel secondo volume [5], in cui viene dedicato un intero capitolo all'argomento. Nel secondo volume si mostrano ulteriori esempi di integrazione tra SQL e linguaggi di programmazione, presentando strumenti che, nel contesto dell'integrazione tra il mondo del Web e le basi di dati, permettono di inserire codice SQL all'interno di moduli software responsabili di generare pagine HTML.

6.1 Procedure Lo standard S Q L - 2 p r e v e d e la definizione di p r o c e d u r e , a n c h e dette stored procedures per il fatto che n o r m a l m e n t e v e n g o n o m e m o r i z z a t e a l l ' i n t e r n o della base di dati c o m e parti dello s c h e m a . C o m e a c c a d e nei linguaggi di p r o g r a m m a z i o n e , le p r o c e d u r e p e r m e t t o n o di associare un n o m e a u n ' i s t r u z i o n e S Q L , con la possibilità di specificare dei parametri da utilizzare per lo s c a m b i o di i n f o r m a z i o n i c o n la p r o c e d u r a . 1 vantaggi s o n o un a u m e n t o della comprensibilità del p r o g r a m m a , u n a più facile manutenibilità, e, nel c a s o delle p r o c e d u r e S Q L , la possibilità di ottenere in diversi casi u n sensibile i n c r e m e n t o delle prestazioni. U n a volta che la p r o c e d u r a è definita, e s s a è utilizzabile c o m e se f a c e s s e parte d e l l ' i n s i e m e dei c o m a n d i S Q L predefiniti. C o n s i d e r i a m o c o m e p r i m o e s e m p i o la p r o c e d u r a S Q L che aggiorna il n o m e della città di un d i p a r t i m e n t o :

procedure AssegnaCitta(:Dip varchar(20), : Citta varchar(20)) update Dipartimento set Città = : Citta where Nome = :Dip; L a p r o c e d u r a p u ò essere invocata a v e n d o c u r a di associare u n valore ai parametri. N e l l ' e s e m p i o si m o s t r a una invocazione della p r o c e d u r a a l l ' i n t e r n o di un p r o g r a m m a C, c h e possiede le due variabili :NomeDipe :NomeCitta:

$ AssegnaCitta(:NomeDip,:NomeCitta) L o standard S Q L - 2 non tratta la scrittura di p r o c e d u r e c o m p l e s s e , m a si limita a specificare la definizione di p r o c e d u r e c o m p o s t e da un singolo c o m a n d o S Q L . Molti sistemi rimuovono q u e s t a limitazione, a n d a n d o incontro alle esigenze delle applicazioni. Le estensioni procedurali proposte dai diversi sistemi d i f f e r i s c o n o m o l t o tra di loro: vi s o n o sistemi che p e r m e t t o n o s o l a m e n t e di associare a ogni p r o c e d u r a una s e q u e n z a di c o m a n d i , altri che invece p e r m e t t o n o l ' u t i l i z z o di strutture di controllo, dichiarazioni di variabili locali e l ' i n v o c a z i o n e di p r o g r a m m i esterni. In ogni caso, l ' u s o di queste f u n z i o n i è fuori dallo standard e r e n d e non portabile il codice S Q L generato. S Q L - 3 estende q u e s t o aspetto del l i n g u a g g i o e f o r n i s c e una ricca sintassi per la definizione di p r o c e d u r e ; fino a che, però, S Q L - 3 non si d i f f o n d e r à , b i s o g n e r à utilizzare i servizi e f f e t t i v a m e n t e disponibili sui sistemi,

preventivando uno sforzo aggiuntivo nel caso in cui si debba adattare la propria applicazione a un altro ambiente. Il seguente esempio mostra una procedura costituita dalla sequenza di due istruzioni SQL. La procedura permette di assegnare all'attributo Città il valore : NuovaCittà, per tutte lerighedi DIPARTIMENTO e IMPIEGATO in cui l'attributo vale : VecchiaCitta. procedure CambiaCittaATutti(:NuovaCitta varchar(20), :VecchiaCitta varchar(20)) begin update Dipartimento set Città = :NuovaCitta where Città = ¡VecchiaCitta; update Impiegato set Città = :NuovaCitta where Città = :VecchiaCitta; end; U n a delle estensioni n o r m a l m e n t e fornite dagli attuali sistemi relazionali è la struttura di controllo if-then-else, che permette di e s p r i m e r e esecuzioni condizionali e p u ò essere usata per rilevare condizioni eccezionali. M o s t r i a m o un e s e m p i o in cui si definisce una p r o c e d u r a che p e r m e t t e di porre a :NuovaCitta il valore dell'attributo Città per tutte le righe di D I P A R T I M E N T O con n o m e :NomeDip; se non si trova un d i p a r t i m e n t o da modificare, si inserisce un e l e m e n t o in ERRORI-

DlP. procedure CambiaCittaADip(:NomeDip varchar(20), :NuovaCitta varchar(20)) if not exists(select * from Dipartimento where Nome = :NomeDip) insert into ErroriDip values(:NomeDip) else update Dipartimento set Città = :NuovaCitta where Nome = :NomeDip; end i f; end; C o m e è già stato a c c e n n a t o , vi s o n o sistemi c o m m e r c i a l i che o f f r o n o un i n s i e m e di estensioni procedurali di S Q L m o l t o a m p i o ; in effetti, tali estensioni s o n o spesso in g r a d o di rendere il l i n g u a g g i o computazionalmente completo, o v v e r o con lo stesso potere espressivo di un n o r m a l e l i n g u a g g i o di p r o g r a m m a z i o n e . Esiste quindi la possibilità di scrivere una intera applicazione con q u e s t o S Q L esteso; tuttavia, è m o l t o raro che q u e s t a sia la soluzione migliore, poiché n o r m a l m e n t e il sistema relazionale è ottimizzato solo per l ' a c c e s s o ai dati.

V e d i a m o infine un e s e m p i o di p r o g r a m m a scritto in P L / S Q L , l ' e s t e n s i o n e p r o c e d u r a l e del s i s t e m a r e l a z i o n a l e O r a c l e Server, per d a r e u n ' i d e a del livello di s o f i s t i c a z i o n e o f f e r t o d a questi sistemi.

procedure Addebita(CodConto char(5), Prelievo integer) is TroppoScoperto exception; AmmontarePrec integer; NuovoAmmontare integer; Limite integer; begin select Ammontare, Scoperto into AmmontarePrec, Limite from ContoCorrente where CodiceConto = CodConto for update of Ammontare; NuovoAmmontare := AmmontarePrec - Prelievo; if NuovoAmmontare > Limite then update ContoCorrente set Ammontare = NuovoAmmontare where CodiceConto = CodConto; else insert into TransazioniOltreScoperto values(CodConto,Prelievo,sysdate); end i f; end Addebita;

L ' e s e m p i o m o s t r a u n a p r o c e d u r a c h e p r e l e v a l ' a m m o n t a r e P r e l i e v o dal c o n to c o n c o d i c e C o d C o n t o se sul c o n t o è p r e s e n t e u n a c o p e r t u r a sufficiente. L a p r o c e d u r a f a u s o di variabili locali ( A m m o n t a r e P r e c , N u o v o A m m o n t a r e e L i m i t e ) e s f r u t t a la struttura di c o n t r o l l o if-then-else.

6.2 Trigger I trigger, detti a n c h e regole attive, r a p p r e s e n t a n o u n a f u n z i o n a l i t à p a r t i c o l a r m e n te significativa dei m o d e r n i sistemi relazionali. I trigger s e g u o n o il p a r a d i g m a Evento-Condizione-Azione ( E C A ) : o g n i t r i g g e r si attiva q u a n d o o c c o r r e u n o specifico e v e n t o a l l ' i n t e r n o d e l l a b a s e di dati; se è s o d d i s f a t t a u n a d a t a c o n d i z i o n e , allora il trigger e s e g u e u n ' a z i o n e stabilita. I trigger r e a l i z z a n o quindi n e l l ' a m b i t o delle basi di dati r e l a z i o n a l i un p a r a d i g m a di p r o g r a m m a z i o n e p r o c e d u r a l e a regole. L o s c o p o è n o r m a l m e n t e q u e l l o di s p e c i f i c a r e le reazioni c h e il s i s t e m a d e v e m e t t e r e in atto in p r e s e n z a di situazioni prestabilite.

S e n z a p r e s e n t a r e in d e t t a g l i o le caratteristiche d e l l a sintassi, m o s t r i a m o un e s e m p i o di t r i g g e r S Q L - 3 .

create trigger ImpiegatiSenzaDip after insert into Impiegati for each row when (new.Dipart is nuli) update Impiegati set Dipart = 'NuoviArrivati' where Matr = new.Matr Il t r i g g e r v i e n e attivato tutte le volte c h e il s i s t e m a rileva l ' i n s e r i m e n t o di t u p l e a l l ' i n t e r n o d e l l a tabella IMPIEGATI. S e la c o n d i z i o n e , r a p p r e s e n t a t a dal p r e d i c a to S Q L c h e s e g u e la p a r o l a c h i a v e w h e n , è s o d d i s f a t t a , o v v e r o se l ' i m p i e g a t o inserito p r e s e n t a il valore n u l l o per l ' a t t r i b u t o D i p a r t , l ' a z i o n e del trigger v i e n e eseguita. In q u e s t o t r i g g e r l ' a z i o n e è r a p p r e s e n t a t a d a un c o m a n d o di u p d a t e c h e a s s e g n a a l l ' a t t r i b u t o D i p a r t del n u o v o i m p i e g a t o il v a l o r e " N u o v i A r r i v a t i " . 11 trigger g a r a n t i s c e c h e la b a s e di dati r e a g i r à a o g n i i n s e r i m e n t o di tuple in IMP I E G A T I aventi valore n u l l o per l ' a t t r i b u t o D i p a r t , a n d a n d o a sostituire il v a l o r e nullo c o n il v a l o r e s o p r a definito. A n a l i z z i a m o b r e v e m e n t e in m o d o i n f o r m a l e la struttura sintattica dei trigger S Q L - 3 . L a parte evento p u ò s o l o p r e s e n t a r e o p e r a z i o n i S Q L di a g g i o r n a m e n t o d e l l o stato della b a s e di dati, o v v e r o i n s e r t e d e l e t e su tabelle, e u p d a t e su tabelle o singoli attributi. O g n i t r i g g e r è sensibile a un s o l o e v e n t o . L a p a r t e condizione è r a p p r e s e n t a t a d a un g e n e r i c o p r e d i c a t o S Q L . N e l l a v a l u t a z i o n e d e l l a c o n d i z i o n e , così c o m e n e l l ' a m b i t o d e l l ' a z i o n e , è p o s s i b i l e utilizzare u n a c o p p i a di variabili p r e d e f i n i t e n e w e old, c h e p e r m e t t o n o di f a r r i f e r i m e n t o rispettivam e n t e alla n u o v a e v e c c h i a v e r s i o n e della t u p l a c h e è stata o g g e t t o del c o m a n d o di insert, update o delete ( n a t u r a l m e n t e , la variabile new n o n sarà utilizzabile n e l l ' a m b i t o di t r i g g e r c h e r e a g i s c o n o a l l ' e v e n t o di delete, così c o m e la variabile old n o n sarà d e f i n i t a p e r trigger c h e r e a g i s c o n o a eventi di insert). Infine, l'azione del t r i g g e r è r a p p r e s e n t a t a d a un g e n e r i c o s i n g o l o c o m a n d o o d a una procedura SQL. 1 trigger s o n o p r e s e n t i nei s i s t e m i r e l a z i o n a l i fin dagli a n n i O t t a n t a , q u i n d i b e n p r i m a della loro s t a n d a r d i z z a z i o n e a v v e n u t a in S Q L - 3 ; p r e s e n t a n o p e r q u e sto m o t i v o delle caratteristiche sintattiche e f u n z i o n a l i e t e r o g e n e e . La p r e s e n z a in S Q L - 3 di u n a sintassi e un m o d e l l o di e s e c u z i o n e ufficiale d e f i n i s c e un o b i e t t i v o verso il q u a l e i sistemi t e n d e r a n n o in f u t u r o , m a a n c o r a o g g i la l i m i t a t a p o r t a b i l i t à dei t r i g g e r c o s t i t u i s c e un o s t a c o l o al loro uso. I trigger p o s s o n o q u i n d i servire alla r e a l i z z a z i o n e di m o l t e p l i c i servizi. U n a delle a p p l i c a z i o n i più c l a s s i c h e dei trigger è r a p p r e s e n t a t a dalla g e s t i o n e di v i n c o li di integrità generici. L ' a p p r o c c i o si b a s a sulla scrittura di t r i g g e r che: (1) s o n o sensibili a tutti gli eventi c h e p o s s o n o i n t r o d u r r e violazioni nei vincoli, (2) verificano nella c o n d i z i o n e se le v i o l a z i o n i s o n o e f f e t t i v a m e n t e presenti e in tal c a s o (3) e s e g u o n o le azioni c h e h a n n o la r e s p o n s a b i l i t à di i n t e r v e n i r e sulla b a s e di dati per e l i m i n a r e le violazioni. Q u e s t o a p p r o c c i o è a p p l i c a b i l e a u n a g r a n d e v a n e t a

di vincoli, a n d a n d o b e n al di là delle t i p o l o g i e di vincoli predetìniti riconosciuti dalla sintassi S Q L . Inoltre, m e d i a n t e i t r i g g e r è p o s s i b i l e gestire la p r e s e n z a di eventuali violazioni dei vincoli i n t e r v e n e n d o sulla b a s e di dati per " r i p a r a r e " l ' i n c o n s i s t e n z a , a d o t t a n d o q u i n d i un a p p r o c c i o c h e p u ò e s s e r e più v i c i n o a quelli c h e s o n o i requisiti d e l l ' a p p l i c a z i o n e , in c o n t r a p p o s i z i o n e alla g e s t i o n e dei vincoli di s i s t e m a p e r i quali il m o d o tipico di reagire alle i n c o n s i s t e n z e c o n s i s t e nel rifiutare l ' a g g i o r n a m e n t o c h e aveva i n t r o d o t t o la v i o l a z i o n e del v i n c o l o . I t r i g g e r s o n o dei costrutti m o l t o ricchi, c h e p r e s e n t a n o un gran n u m e r o di varietà sintattiche e di c o m p o r t a m e n t o e vi s o n o in g e n e r a l e diversi aspetti significativi c h e c a r a t t e r i z z a n o la loro d e f i n i z i o n e . C o m e già s e g n a l a t o , a l l ' a r g o m e n t o è d e d i c a t o un intero c a p i t o l o del s e c o n d o v o l u m e [5]. V o l e n d o rimanere n e l l ' a m b i t o di q u e s t o testo al livello di u n a trattazione introduttiva, si p o s s o n o m e t t e r e in evid e n z a le principali p r o b l e m a t i c h e c h e r e n d o n o difficile s f r u t t a r e a p p i e n o q u e s t o s t r u m e n t o così p o t e n t e e flessibile. II p r i n c i p a l e p r o b l e m a c h e si p r e s e n t a a chi v u o l e s f r u t t a r e il p o t e n z i a l e dei t r i g g e r è d a t o dalla c o m p l e s s i t à del c o m p o r t a m e n t o di un s i s t e m a c o m p o s t o d a m o l t e p l i c i trigger. U n o degli aspetti c a r a t t e r i z z a n t i dei t r i g g e r è il fatto c h e i t r i g g e r d e v o n o reagire a eventi di m o d i f i c a della b a s e di dati, q u a l u n q u e sia la loro origine, e c h e l ' a z i o n e del trigger p u ò a s u a volta m o d i f i c a r e lo stato della b a s e di dati. U n a c o n s e g u e n z a di c i ò è c h e l ' a z i o n e di un trigger p u ò a sua volta p r o d u r r e eventi c h e attivano altri trigger, c r e a n d o delle c a t e n e di e s e c u z i o n e c h e r i s u l t a n o di n o r m a assai difficili da a n a l i z z a r e . L e c a t e n e di a t t i v a z i o n e p o s s o n o inoltre d e g e n e r a r e , d a n d o l u o g o ad attivazioni infinite, c h e si p o s s o n o verificare q u a n d o vi s o n o t r i g g e r c h e si attivano m u t u a m e n t e in m o d o ciclico. L a g e s t i o n e di q u e s t e situazioni è p a r t i c o l a r m e n t e difficile e r i c h i e d e di far u s o di s t r u m e n t i sofisticati, c h e n o n s o n o c o m u n q u e risolutivi. In pratica, lo s v i l u p p o di sistemi di trigger r i c h i e d e un n o t e v o l e i m p e g n o d a p a r t e del p r o g e t t i s t a d e l l a b a s e di dati. Per c o n c l u d e r e , si p u ò m e t t e r e in e v i d e n z a c o m e il p o t e n z i a l e dei trigger sia c o m u n q u e e s t r e m a m e n t e elevato e q u i n d i è b e n e c h e ogni u t e n t e a v a n z a t o di un s i s t e m a r e l a z i o n a l e sia a c o n o s c e n z a delle caratteristiche di q u e s t o s t r u m e n t o , per p o t e r gestire in m o d o e f f i c a c e diversi requisiti d e l l e a p p l i c a z i o n i , nella situazioni nelle quali si h a la g a r a n z i a c h e il c o m p o r t a m e n t o del s i s t e m a n o n p o s s a d a r e luogo a comportamenti anomali.

6.3 SQL Embedded L i n t e g r a z i o n e del l i n g u a g g i o S Q L c o n i n o r m a l i l i n g u a g g i di p r o g r a m m a z i o n e di alto livello (C, C + + , C O B O L , Java, ...) p r e s e n t a alcuni ostacoli. 11 p r i m o p r o b l e m a deriva d a l fatto c h e S Q L è un l i n g u a g g i o m o l t o ricco, c o n u n a p r o p r i a sintassi. S o n o state p r o p o s t e d u e soluzioni per c o n s e n t i r e l ' u s o di S Q L a l l ' i n t e r n o di un n o r m a l e l i n g u a g g i o di p r o g r a m m a z i o n e : l ' i n c a s t o n a m e n t o ( S Q L E m b e d d e d ) e 1 u s o di Cali Level Interface. P a r l e r e m o più avanti della s e c o n d a s o l u z i o n e . L i n c a s t o n a m e n t o p r e v e d e di introdurre d i r e t t a m e n t e nel p r o g r a m m a s o r g e n t e scritto nel l i n g u a g g i o di alto livello le istruzioni S Q L , d i s t i n g u e n d o l e dalle n o r m a l i

istruzioni tramite un o p p o r t u n o separatore. Lo standard S Q L prevede che il c o d i c e SQL sia p r e c e d u t o dalla stringa exec sql e termini con il carattere Dal p u n t o di vista d e l l ' i m p l e m e n t a z i o n e , b i s o g n e r à far p r e c e d e r e la c o m p i lazione del l i n g u a g g i o di alto livello d a l l ' e s e c u z i o n e di un a p p o s i t o p r e p r o c e s s o re che r i c o n o s c e r à le istruzioni S Q L e sostituirà a esse un insieme o p p o r t u n o di c h i a m a t e ai servizi del D B M S , tramite una libreria specifica per ogni sistema. Il p r e p r o c e s s o r e riconoscerà il significato dei singoli c o m a n d i S Q L e sarà in grad o di predisporre l ' i n s i e m e o p p o r t u n o di strutture ausiliarie richieste per la loro e s e c u z i o n e . 11 p r e p r o c e s s o r e sarà inoltre in g r a d o di segnalare al m o m e n t o della c o m p i l a z i o n e eventuali a n o m a l i e n e l l ' u s o di S Q L . Q u e s t o risulta uno dei m o d i più agevoli per realizzare l ' i n t e g r a z i o n e tra il ling u a g g i o di p r o g r a m m a z i o n e e S Q L , in q u a n t o b u o n a parte dei p r o b l e m i v e n g o n o gestiti in m o d o a u t o m a t i c o dal preprocessore. A f f i n c h é la s o l u z i o n e sia applicabile, è necessario che sia disponibile un p r e p r o c e s s o r e per la particolare c o m b i nazione di D B M S - p i a t t a f o r m a - l i n g u a g g i o - c o m p i l a t o r e usato per lo s v i l u p p o (per e s e m p i o , Oracle Server, Solaris, C, gcc). I sistemi c o m m e r c i a l i di m a g g i o r e d i f f u sione m e t t o n o a disposizione soluzioni di q u e s t o tipo per le configurazioni d ' u s o più f r e q u e n t e . U n e s e m p i o d ' u s o di S Q L E m b e d d e d a p p a r e in Figura 6.1, dove si usa c o n c r e t a m e n t e la soluzione E C P G , un p r e p r o c e s s o r e di S Q L E m b e d d e d per il ling u a g g i o C e Postgres. L ' e s e m p i o in Figura 6.1 presenta alcune caratteristiche che vale la p e n a di mettere in evidenza. In p r i m o luogo, il p r e p r o c e s s o r e introduce i m p l i c i t a m e n te la d i c h i a r a z i o n e di una particolare struttura, s q l c a ( S Q L C o m m u n i c a t i o n

(1) #include (2) main() (3) { exec sql begin declare section; (4) char *NomeDip = "Manutenzione"; (5) char *CittaDip = "Pisa"; (6) int NumeroDip = 20; (7) exec sql end declare section; (8) (9) (10) (11) (12) (13)

exec sql connect to utente@librobd; if (sqlca.sqlcode != 0) { printf("Connessione al DB non riuscita\n"); else { exec sql insert into Dipartimento values(:NomeDip,:CittaDip,:NumeroDip)

exec sql disconnect all; (14) (!5) } (16) } Figura 6.1 Un p r o g r a m m a C con SQL Embedded

Area). Si tratta di una struttura dati che permette di gestire la c o m u n i c a z i o n e tra il p r o g r a m m a in e s e c u z i o n e e il D B M S . Q u e s t a struttura è visibile alla linea (10) del p r o g r a m m a , dove si f a a c c e s s o al c a m p o sqlcode della struttura. Il c a m p o sqlcode ha proprio lo s c o p o di m a n t e n e r e il codice d ' e r r o r e d e l l ' u l t i m o c o m a n do S Q L inviato al D B M S . Un valore pari a zero significa c h e il c o m a n d o è stato gestito con successo; un valore diverso da zero segnala invece che si è verificata u n ' a n o m a l i a e il c o m a n d o non è a n d a t o a b u o n fine. Si p u ò osservare c o m e le dichiarazioni di variabili del p r o g r a m m a C siano racchiuse (linee (4) e (8)) d a una c o p p i a di c o m a n d i begin declare s e c t i o n ed end declare section. Q u e s t o p a s s o è necessario se si d e s i d e r a n o poi utilizzare le variabili del p r o g r a m m a c o m e p a r a m e t r i per i c o m a n d i S Q L . Si osserva infatti c o m e le variabili del l i n g u a g g i o v e n g a n o usate nel c o m a n d o di ins e r i m e n t o che c o m p a r e alla linea (13) del p r o g r a m m a . Il m e c c a n i s m o che viene o f f e r t o per l ' u s o delle variabili è m o l t o agevole e richiede s o l a m e n t e di far precedere il n o m e della variabile dal carattere di d u e punti. Si osserva infine che in q u e s t o e s e m p i o , così c o m e varrà per i successivi, si a s s u m e un m o d e l l o di interazione con la base di dati che prevede che ogni singolo c o m a n d o sia gestito d a u n a singola transazione, con un commit eseguito a u t o m a t i c a m e n t e al termine di ogni c o m a n d o (cosiddetto autocommit). C i ò evita di introdurre negli e s e m p i i c o m a n d i espliciti di chiusura della transazione. U n i m p o r t a n t e p r o b l e m a che caratterizza l ' i n t e g r a z i o n e tra S Q L e i normali linguaggi di p r o g r a m m a z i o n e è il cosidetto p r o b l e m a del conflitto d'impedenza (impedance mismatch'). I linguaggi di p r o g r a m m a z i o n e a c c e d o n o agli elementi di u n a tabella s c a n d e n d o n e le righe una a una, utilizzando quello c h e viene detto un a p p r o c c i o tuple-oriented. Al contrario, S Q L è un l i n g u a g g i o di tipo set-oriented, che o p e r a su intere tabelle, non su singole righe, e c h e restituisce c o m e risultato di una interrogazione u n ' i n t e r a tabella. Q u e s t o p r o b l e m a a m m e t t e due diverse soluzioni. L a p r i m a soluzione si b a s a s u l l ' u s o dei cursori. I cursori f a n n o parte dello standard S Q L fin dalla versione S Q L - 2 e non p o n g o n o particolari restrizioni sul l i n g u a g g i o di p r o g r a m m a z i o n e . U n a s e c o n d a soluzione consiste nell'utilizzare un l i n g u a g g i o di p r o g r a m m a zione che abbia a disposizione dei costruttori di dati più potenti e in particolare riesca a gestire in m o d o naturale u n a struttura del tipo " i n s i e m e di righe". Q u e s t a è una soluzione che sta d i v e n t a n d o s e m p r e più interessante, grazie alla c r e s c e n te d i f f u s i o n e dei linguaggi di p r o g r a m m a z i o n e a oggetti, caratterizzati da potenti m e c c a n i s m i di definizione e gestione di tipi. Le soluzioni A D O , A D O . N E T e J D B C c h e d e s c r i v e r e m o in seguito ( P a r a g r a f o 6.4) s e g u o n o questa i m p o s t a z i o n e per la risoluzione del p r o b l e m a .

II termine deriva dall'ingegneria elettronica, dove si richiede che nell'accoppiamento di circuiti elettronici le impedenze d'ingresso e di uscita dei circuiti collegati siano il più possibile simili.

6.3.1 Cursori Un c u r s o r e è u n o s t r u m e n t o c h e p e r m e t t e a un p r o g r a m m a di a c c e d e r e alle r i g h e di u n a tabella u n a alla volta; il c u r s o r e v i e n e d e f i n i t o su u n a g e n e r i c a i n t e r r o g a z i o n e . V e d i a m o d a p p r i m a la sintassi per la d e f i n i z i o n e e l ' u s o dei c u r s o r i :

declare NomeCursore [ scroll ] cursor for SelectSQL [ for ( read only | update [ of Attributo { , Attributo } ] ) ] Il c o m a n d o declare cursor d e f i n i s c e un c u r s o r e , a s s o c i a t o a u n a p a r t i c o l a r e i n t e r r o g a z i o n e sulla b a s e di dati. L ' o p z i o n e s c r o l l s p e c i f i c a se si v u o l e perm e t t e r e al p r o g r a m m a di m u o v e r s i l i b e r a m e n t e sul risultato d e l l ' i n t e r r o g a z i o n e . L ' o p z i o n e finale f o r u p d a t e s p e c i f i c a se il c u r s o r e d e v e e s s e r e utilizzato nell ' a m b i t o di un c o m a n d o di m o d i f i c a , p e r m e t t e n d o di s p e c i f i c a r e e v e n t u a l m e n t e gli attributi c h e s a r a n n o o g g e t t o del c o m a n d o di update.

open

NomeCursore

Il c o m a n d o o p e n h a c o m e a r g o m e n t o un c u r s o r e . Al m o m e n t o d e l l ' e s e c u z i o ne del c o m a n d o o p e n , v i e n e e s e g u i t a l ' i n t e r r o g a z i o n e a s s o c i a t a al c u r s o r e e il risultato d i v e n t a a c c e s s i b i l e t r a m i t e l ' i s t r u z i o n e f e t c h .

f etch [ Posizione f rom ] NomeCursore

into

ListaDiFetch

Il c o m a n d o f e t c h p r e n d e u n a riga dal c u r s o r e e la ripone nelle variabili del p r o g r a m m a c h e c o m p a i o n o in ListaDiFetch. In ListaDiFetch vi sarà u n a variabile p e r o g n i e l e m e n t o della target list d e l l a i n t e r r o g a z i o n e , con u n a c o r r i s p o n d e n z a d e t t a ta d a l l ' o r d i n a m e n t o nella lista e in cui o g n i e l e m e n t o è c o m p a t i b i l e c o n i d o m i n i degli e l e m e n t i della target list. Esiste l ' i m p o r t a n t e c o n c e t t o di riga c o r r e n t e , c h e r a p p r e s e n t a l ' u l t i m a riga letta. Il p a r a m e t r o Posizione p e r m e t t e di s p e c i f i c a r e q u a le riga d o v r à e s s e r e o g g e t t o d e l l ' o p e r a z i o n e di f e t c h ; il p a r a m e t r o p u ò a s s u m e r e i valori: • • • • •

n e x t (la riga s u c c e s s i v a alla c o r r e n t e ) ; p r i o r (la riga p r e c e d e n t e alla c o r r e n t e ) ; f i r s t (la p r i m a riga del risultato); l a s t ( l ' u l t i m a riga del risultato); a b s o l u t e Espressionelntera (la riga c h e c o m p a r e in p o s i z i o n e / - e s i m a nel c u r s o r e , se i è il risultato d e l l a v a l u t a z i o n e d e l l ' e s p r e s s i o n e ) ; • r e l a t i v e Espressionelntera ( c o m e a b s o l u t e , solo c h e v i e n e p r e s o c o m e p u n t o di riferimento la p o s i z i o n e della riga c o r r e n t e ) . Q u e s t e o p z i o n i s o n o utilizzabili a c o n d i z i o n e c h e sia stata s p e c i f i c a t a al m o m e n t o della d e f i n i z i o n e del c u r s o r e l ' o p z i o n e s c r o l l , la q u a l e a p p u n t o g a r a n t i s c e c h e sia possibile m u o v e r s i l i b e r a m e n t e a l l ' i n t e r n o del risultato d e l l ' i n t e r r o g a z i o n e . Se l ' o p z i o n e s c r o l l n o n è s p e c i f i c a t a , l ' u n i c o v a l o r e a c c e t t a b i l e per il p a r a m e t r o

Posizione è n e x t . In q u e s t o c a s o , l ' i m p l e m e n t a z i o n e p u ò d i v e n t a r e più e f f i c i e n te: le righe del risultato p o s s o n o e s s e r e scartate i m m e d i a t a m e n t e d o p o e s s e r e state restituite al p r o g r a m m a , r i l a s c i a n d o m e m o r i a c h e p u ò e s s e r e utilizzata da altri c o m p o n e n t i del s i s t e m a ; inoltre, i t e m p i di r i s p o s t a p o s s o n o e s s e r e ridotti, perc h é non b i s o g n a aspettare c h e la v a l u t a z i o n e della q u e r y sia c o m p l e t a t a p r i m a di p o t e r a c c e d e r e al risultato. T u t t o ciò è utile s o p r a t t u t t o q u a n d o l ' i n t e r r o g a z i o n e restituisce un gran n u m e r o di righe. I c o m a n d i di u p d a t e e d e l e t e p e r m e t t o n o di a p p o r t a r e m o d i f i c h e alla b a s e di dati tramite l ' u s o di cursori, nel m o d o descritto dalle sintassi seguenti. update NomeTabella s e t Attributo = ( Espressione \null |default ) {, Attributo = ( Espressione | n u l l | d e f a u l t >} w h e r e c u r r e n t of NomeCursore delete

f r o m NomeTabella

where

current

of

NomeCursore

L ' u n i c a e s t e n s i o n e rispetto ai c o m a n d i di u p d a t e e d e l e t e g i à visti c o n s i s t e nella p r e s e n z a nella c l a u s o l a w h e r e del p r e d i c a t o c u r r e n t o f NomeCursore, c h e i d e n t i f i c a la riga c o r r e n t e ( a f f i n c h é v e n g a a g g i o r n a t a o r i m o s s a ) . I c o m a n d i di m o d i f i c a s o n o utilizzabili solo nel c a s o in cui il c u r s o r e p e r m e t t a di a c c e d e r e a u n a riga e f f e t t i v a di u n a tabella, n o n e s s e n d o a p p l i c a b i l i q u a n d o la q u e r y a s s o c i a t a al c u r s o r e e s e g u e un j o i n tra diverse tabelle.

ciose

NomeCursore

Il c o m a n d o c l o s e c h i u d e il c u r s o r e , o v v e r o c o m u n i c a al s i s t e m a c h e il risultato d e l l ' i n t e r r o g a z i o n e n o n s e r v e più. A q u e s t o p u n t o v e n g o n o liberate le risorse d e d i c a t e al c u r s o r e , in p a r t i c o l a r e rilasciando lo s p a z i o di m e m o r i a utilizzato p e r c o n s e r v a r e il risultato. U n s e m p l i c e e s e m p i o di d i c h i a r a z i o n e di c u r s o r e è: declare Cursorelmpiegati scroll cursor for s e l e c t Cognome, Nome, Stipendio from Impiegato w h e r e S t i p e n d i o > 40 a n d S t i p e n d i o < 100 V i e n e così a s s o c i a t o il c u r s o r e C u r s o r e l m p i e g a t i alla i n t e r r o g a z i o n e c h e p e r m e t t e di o t t e n e r e i dati relativi ai d i p e n d e n t i c h e g u a d a g n a n o tra 4 0 e 100 m i l a Euro. Nella F i g u r a 6.2 v e d i a m o un s e m p l i c e e s e m p i o di p r o c e d u r a C c h e fa u s o dei cursori. Le variabili del p r o g r a m m a v e n g a n o r a p p r e s e n t a t e nei c o m a n d i S Q L con il n o m e p r e c e d u t o dal c a r a t t e r e " : " (due punti). Le variabili d e v o n o e s s e r e d i c h i a rate di tipo c o m p a t i b i l e ai valori c h e d o v r a n n o c o n t e n e r e . Per r i c o n o s c e r e q u a n d o il c u r s o r e ha t e r m i n a t o di estrarre tutte le righe, si f a u s o del c a m p o s q l c o d e della s t r u t t u r a p r e d e f i n i t a s q l c a .

(1) (2)

void visualizzaStipendiDipart(char {

NomeDip[])

(3)

exec sql begin declare section;

(4) (5)

char Nome[20], Cognome[20]; long int Stipendio;

(6)

exec sql end declare section;

(7)

(10) (11)

exec sql declare ImpDip cursor for select Nome, Cognome, Stipendio from Impiegato where Dipart = :NomeDip; exec sql open ImpDip; exec sql fetch ImpDip into :Nome, : Cognome, : Stipendio ; printf("Dipartimento %s\n",NomeDip); while (sqlca.sqlcode == 0)

(12)

{

(8) (9)

(13)

printf("Nome e cognome dell'impiegato: %s %s", Nome,Cognome); printf("Attuale stipendio: %d\n",Stipendio); exec sql fetch ImpDip into :Nome, ¡Cognome, : Stipendio;

(14) (15) (16)

}

(17)

exec sql close cursor ImpDip;

(18)

}

F i g u r a 6.2 U n a p r o c e d u r a C c h e f a u s o di cursori

Le interrogazioni per cui è garantito che v e n g a restituita una sola riga (per e s e m p i o perché nella c o n d i z i o n e c o m p a r e un predicato di u g u a g l i a n z a con una chiave) v e n g o n o dette query scalari; per queste interrogazioni è possibile utilizzare una semplice interfaccia tra S Q L e il linguaggio di p r o g r a m m a z i o n e , che non richiede di definire un cursore. Si p u ò infatti in q u e s t o c a s o fare uso della clausola i n t o , mediante la quale si stabilisce in m o d o diretto a quali variabili del p r o g r a m m a d e b b a essere assegnato il risultato della interrogazione. Un e s e m p i o è il seguente:

select Nome, Cognome into :nomeDip, :cognomeDip from Dipendente where Matricola = :matrDip;

1 valori degli attributi N o m e e C o g n o m e del d i p e n d e n t e la cui matricola è c o n t e n u t a nella variabile matrDip v e r r a n n o copiati nelle variabili nomeDip e

cognomeDip.

6.3.2 SQL dinamico In diverse situazioni sorge la n e c e s s i t à di p e r m e t t e r e a l l ' a p p l i c a z i o n e di d e f i n i r e al m o m e n t o d e l l ' e s e c u z i o n e le i n t e r r o g a z i o n i d a e f f e t t u a r e sulla b a s e di dati. Se le i n t e r r o g a z i o n i h a n n o u n a struttura p r e d e f i n i t a e c i ò c h e varia è s o l a m e n t e il valore dei p a r a m e t r i usati n e l l ' i n t e r r o g a z i o n e , allora d i v e n t a possibile c o s t r u i r e u n a a p p l i c a z i o n e c h e g e s t i s c e le t i p o l o g i e di i n t e r r o g a z i o n e richieste d a l l ' u t e n t e s f r u t t a n d o il m e c c a n i s m o di p a s s a g g i o dei p a r a m e t r i d a l l ' a m b i e n t e del p r o g r a m m a al s i s t e m a di g e s t i o n e di basi di dati, c o m e illustrato negli e s e m p i del p a r a g r a f o p r e c e d e n t e . In altri casi p e r ò l ' u t e n t e h a b i s o g n o di e f f e t t u a r e d e l l e i n t e r r o g a z i o n i c a r a t t e r i z z a t e d a e s t r e m a variabilità, c o n la n e c e s s i t à di d e f i n i r e al m o m e n t o dell ' e s e c u z i o n e del p r o g r a m m a n o n solo i valori dei p a r a m e t r i , m a a n c h e la f o r m a delle i n t e r r o g a z i o n i , l ' i n s i e m e di tabelle cui a c c e d e r e e la struttura del risultato. I m e c c a n i s m i per l ' i n v o c a z i o n e di c o m a n d i S Q L a l l ' i n t e r n o dei p r o g r a m m i c h e a b b i a m o visto finora non v a n n o b e n e in q u e s t o c o n t e s t o , d a t o c h e r i c h i e d o n o c h e la struttura della i n t e r r o g a z i o n e sia p r e f i s s a t a (si p a r l a infatti di S Q L statico). U n a f a m i g l i a alternativa di c o m a n d i , c h e rientra s e m p r e tra le s o l u z i o n i c o n S Q L E m b e d d e d , p e r m e t t e l ' u s o di S Q L dinamico. C o n questi c o m a n d i è p o s s i b i l e c o s t r u i r e un p r o g r a m m a c h e e s e g u e delle istruzioni S Q L c o s t r u i t e al m o m e n t o d e l l ' e s e c u z i o n e del p r o g r a m m a . Q u e s t o m e c c a n i s m o richiede p e r ò u n s u p p o r t o speciale d a parte del sistema. Il p r o b l e m a p r i n c i p a l e c h e d e v e e s s e r e a f f r o n t a t o è c o s t i t u i t o dal p a s s a g g i o di i n f o r m a z i o n i tra il p r o g r a m m a e il c o m a n d o S Q L . Visto c h e il c o m a n d o S Q L è arbitrario, il p r o g r a m m a n o n h a m o d o di c o n o s c e r e al m o m e n t o d e l l a c o m p i l a z i o n e quali s o n o i p a r a m e t r i richiesti in i n g r e s s o e q u a l i s o n o le caratteristiche d e l l ' e v e n t u a l e risultato p r o d o t t o d a l l ' e s e c u z i o n e del c o m a n d o . Q u e s t e i n f o r m a z i o n i s o n o p e r ò n e c e s s a r i e a f f i n c h é il p r o g r a m m a sia in g r a d o di gestire l ' i n t e r r o g a z i o n e al s u o i n t e r n o . L ' u s o di S Q L d i n a m i c o m o d i f i c a la m o d a l i t à di i n t e r a z i o n e c o n il s i s t e m a . N e l c a s o di S Q L statico, i c o m a n d i S Q L v e n g o n o gestiti d a un p r e p r o c e s s o r e c h e a n a l i z z a la struttura del c o m a n d o e ne p u ò c o s t r u i r e u n a t r a d u z i o n e nel l i n g u a g gio i n t e r n o del s i s t e m a . In q u e s t o m o d o il c o m a n d o n o n deve e s s e r e a n a l i z z a t o e o t t i m i z z a t o o g n i volta c h e v i e n e richiesta la sua e s e c u z i o n e . C i ò p o r t a dei c o n s i derevoli v a n t a g g i in t e r m i n i di p r e s t a z i o n i . S Q L d i n a m i c o c e r c a di o f f r i r e q u a n d o p o s s i b i l e questi v a n t a g g i , m e t t e n d o a d i s p o s i z i o n e d u e diverse m o d a l i t à di inter a z i o n e : si p u ò e s e g u i r e d i r e t t a m e n t e l ' i n t e r r o g a z i o n e , p e r cui a l l ' a n a l i s i s e g u e i m m e d i a t a m e n t e l ' e s e c u z i o n e della i n t e r r o g a z i o n e , o la g e s t i o n e della i n t e r r o g a z i o n e p u ò a v v e n i r e in d u e fasi: u n a p r i m a f a s e di analisi e u n a s e c o n d a f a s e in cui l'interrogazione viene propriamente eseguita.

Esecuzione immediata M e d i a n t e il c o m a n d o di e x e c u t e immediate si r i c h i e d e l ' e s e c u z i o n e di u n a i s t r u z i o n e S Q L , specificata d i r e t t a m e n t e o c o n t e n u t a in un p a r a m e t r o di tipo stringa di caratteri d e l l ' a m b i e n t e del p r o g r a m m a : execute immediate IstruzioneSQL

Il m o d o i m m e d i a t o p u ò e s s e r e utilizzato s o l o p e r c o m a n d i c h e n o n richiedono p a r a m e t r i n é in i n g r e s s o n é in uscita, c o m e p e r e s e m p i o a l c u n i c o m a n d i di i n s e r i m e n t o e c a n c e l l a z i o n e . U n e s e m p i o d ' u s o del c o m a n d o è il s e g u e n t e :

exec sql execute immediate "delete from Impiegato where Nome = 'Mario'" In un p r o g r a m m a C si p o t r e b b e invece scrivere:

istruzioneSql "delete from= Impiegato where Nome = 'Mario'"; exec sql execute immediate :istruzioneSql; Q u a n d o p e r ò un c o m a n d o v i e n e e s e g u i t o più volte, o q u a n d o il p r o g r a m m a d e v e gestire u n o s c a m b i o di p a r a m e t r i di i n g r e s s o o di uscita c o n l ' i s t r u z i o n e , d i v e n t a n e c e s s a r i o d i s t i n g u e r e le d u e fasi di p r e p a r a z i o n e e di e s e c u z i o n e .

Fase di preparazione II c o m a n d o prepare a n a l i z z a u n ' i s t r u z i o n e S Q L e la t r a d u c e nel l i n g u a g g i o p r o c e d u r a l e i n t e r n o del s i s t e m a . Il c o m a n d o p r e p a r e a s s o c i a alla t r a d u z i o n e d e l l ' i s t r u z i o n e u n n o m e , c h e p u ò e s s e r e poi u s a t o d a g l i altri c o m a n d i : prepare NomeComando from IstruzioneSQL L ' i s t r u z i o n e S Q L p u ò c o n t e n e r e dei p a r a m e t r i in i n g r e s s o , r a p p r e s e n t a t i dal c a r a t tere di p u n t o interrogativo. P e r e s e m p i o :

prepare : comando from "select Città from Dipartimento where Nome = ?" In q u e s t o m o d o alla variabile comando del p r o g r a m m a c o r r i s p o n d e la t r a d u z i o n e d e l l a istruzione, c o n un p a r a m e t r o di i n g r e s s o c h e r a p p r e s e n t a il n o m e del d i p a r t i m e n t o c h e d e v e e s s e r e s e l e z i o n a t o dalla i n t e r r o g a z i o n e . Q u a n d o u n a i s t r u z i o n e S Q L c h e e r a stata t r a d o t t a n o n serve più, è p o s s i b i le rilasciare la m e m o r i a o c c u p a t a dalla t r a d u z i o n e d e l l ' i s t r u z i o n e u t i l i z z a n d o il c o m a n d o di deallocate prepare, c o n la s e g u e n t e sintassi:

deallocate prepare NomeComando P e r e s e m p i o , per d e a l l o c a r e il c o m a n d o p r e c e d e n t e , si p o t r à utilizzare il s e g u e n t e comando:

deallocate prepare : comando

F a s e di e s e c u z i o n e Per e s e g u i r e un c o m a n d o c h e è stato p r e e l a b o r a t o da u n a p r e p a r e si u s a il c o m a n d o di e x e c u t e , c o n la s e g u e n t e sintassi:

execute NomeComando

[ into ListaTarget ] [ using ListaParametri

]

L a lista dei target c o n t i e n e l ' e l e n c o dei p a r a m e t r i in cui d e v e e s s e r e scritto il risultato d e l l ' e s e c u z i o n e del c o m a n d o ( q u e s t a parte è o p z i o n a l e q u a l o r a il c o m a n d o S Q L n o n restituisca dei valori). L a lista dei p a r a m e t r i s p e c i f i c a invece quali s o n o i valori c h e d e v o n o e s s e r e assunti dai p a r a m e t r i variabili della lista ( a n c h e q u e s t a parte p u ò n o n e s s e r e p r e s e n t e q u a l o r a il c o m a n d o S Q L sia privo di p a r a m e t r i ) . U n e s e m p i o p u ò e s s e r e il s e g u e n t e :

execute : comando into : citta using : dipartimento S u p p o n e n d o c h e la variabile del p r o g r a m m a d i p a r t i m e n t o a b b i a c o m e valore la stringa 'Produzione', l ' e f f e t t o di q u e s t o c o m a n d o è di e s e g u i r e la q u e r y :

select Città from Dipartimento where Nome = 'Produzione' e di o t t e n e r e c o m e c o n s e g u e n z a la stringa programma.

'Torino' nella variabile citta del

Cursori con SQL dinamico L ' u s o dei c u r s o r i c o n S Q L d i n a m i c o è m o l t o sim i l e a l l ' u s o dei cursori c h e v i e n e f a t t o d a S Q L statico. L e u n i c h e d u e d i f f e r e n z e c o n s i s t o n o nel f a t t o c h e si a s s o c i a al c u r s o r e l ' i d e n t i f i c a t i v o d e l l a i n t e r r o g a z i o n e invece c h e l ' i n t e r r o g a z i o n e stessa, e c h e i c o m a n d i d ' u s o del c u r s o r e a m m e t t o n o la specifica delle c l a u s o l e i n t o e u s i n g c h e p e r m e t t o n o la s p e c i f i c a degli eventuali p a r a m e t r i di i n g r e s s o e di uscita. U n e s e m p i o d ' u s o di un c u r s o r e d i n a m i c o è il s e g u e n t e , in cui si s u p p o n e c h e l ' i n t e r r o g a z i o n e d e f i n i t a nella stringa i s t r u z i o n e S Q L a m m e t t a un p a r a m e t r o :

prepare ¡comando from :istruzioneSQL declare Cursore cursor for ¡comando open Cursore using rnomel

6.4 Cali Level Interface (CLI) L e s o l u z i o n i c h e s o n o state descritte fino a o r a r i c a d o n o nella f a m i g l i a delle soluzioni S Q L E m b e d d e d , d o v e si p r e v e d e di d i s p o r r e di un p r e p r o c e s s o r e c h e e s p a n d e c o m a n d i S Q L presenti a l l ' i n t e r n o di u n n o r m a l e l i n g u a g g i o di p r o g r a m m a z i o n e . 11 p r e p r o c e s s o r e non f a altro c h e tradurre i c o m a n d i S Q L in u n i n s i e m e o p p o r t u n o di c h i a m a t e di s o t t o p r o g r a m m i c h e s o n o p r e s e n t i nella libreria o f f e r t a dal D B M S e c h e r e a l i z z a n o il d i a l o g o c o n la b a s e di dati.

U n a s o l u z i o n e a l t e r n a t i v a c o n s i s t e nel m e t t e r e d i r e t t a m e n t e a d i s p o s i z i o n e del p r o g r a m m a t o r e un i n s i e m e di f u n z i o n i c h e p e r m e t t a n o di i n t e r a g i r e c o n il D B M S . Q u e s t a f a m i g l i a di s o l u z i o n i va s o t t o il n o m e di Cali Level Interface, in q u a n t o il p r o g r a m m a t o r e d i s p o n e d i r e t t a m e n t e di u n a libreria di f u n z i o n i p e r r e a l i z z a r e il d i a l o g o c o n la b a s e di dati. R i s p e t t o alla s o l u z i o n e S Q L E m b e d d e d , c o n la C L I si d i s p o n e n o r m a l m e n t e di u n o s t r u m e n t o più flessibile, m e g l i o i n t e g r a t o c o n il ling u a g g i o di p r o g r a m m a z i o n e , c o n l ' i n c o n v e n i e n t e di d o v e r g e s t i r e e s p l i c i t a m e n t e aspetti c h e in S Q L E m b e d d e d v e n g o n o risolti a u t o m a t i c a m e n t e dal p r e p r o c e s s o r e . Diversi sistemi o f f r o n o d e l l e p r o p r i e C L I . Il m o d o g e n e r a l e d ' u s o di q u e s t i s t r u m e n t i è il s e g u e n t e . 1. Si utilizza un s e r v i z i o d e l l a C L I p e r c r e a r e u n a c o n n e s s i o n e c o n il D B M S . 2. Si invia sulla c o n n e s s i o n e u n c o m a n d o S Q L c h e r a p p r e s e n t a la richiesta. 3. Si riceve c o m e r i s p o s t a del c o m a n d o u n a s t r u t t u r a r e l a z i o n a l e in u n o p p o r t u n o f o r m a t o ; la C L I d i s p o n e di u n c e r t o i n s i e m e di p r i m i t i v e c h e p e r m e t t o n o di a n a l i z z a r e e d e s c r i v e r e la s t r u t t u r a del risultato del c o m a n d o . 4. Al t e r m i n e d e l l a s e s s i o n e di lavoro, si c h i u d e la c o n n e s s i o n e e si rilasciano le s t r u t t u r e dati u t i l i z z a t e p e r la g e s t i o n e d e l d i a l o g o . A n c h e in q u e s t o c a m p o d i v e r s e i n i z i a t i v e h a n n o p o r t a t o alla d e f i n i z i o n e di s p e c i f i c h e e alla loro i m p l e m e n t a z i o n e , c o n s e n t e n d o agli s v i l u p p a t o r i di r e a l i z z a r e a p p l i c a z i o n i c h e a c c e d o n o a basi di dati in m o d o r e l a t i v a m e n t e f a c i l e . D e s c r i v e r e m o q u i n d i i n i z i a l m e n t e le s o l u z i o n i c h e c a r a t t e r i z z a n o la p i a t t a f o r m a s o f t w a r e M i c r o s o f t ( O D B C , O L E D B , A D O e A D O . N E T ) . P r e s e n t e r e m o p o i la s o l u z i o ne J D B C , c h e r a p p r e s e n t a i n v e c e la s o l u z i o n e di riferimento p e r q u a n t o r i g u a r d a lo s v i l u p p o di a p p l i c a z i o n i nel l i n g u a g g i o Java. In F i g u r a 6 . 3 v i e n e m o s t r a t o u n quadro riassuntivo delle diverse soluzioni.

ODBC

O L E DB

ADO

ADO.NET

JDBC

Interfaccia standard che permette di accedere a basi di dati in qualunque contesto, realizzando interoperabilità con diverse combinazioni di DBMS-Sist.Op.-Reti Soluzione proprietaria Microsoft, basata sul modello C O M , che permette ad applicazioni Windows di accedere a sorgenti dati generiche (non solo D B M S ) Soluzione proprietaria Microsoft che permette di sfruttare i servizi OLE DB. utilizzando un'interfaccia record-oriented Soluzione proprietaria Microsoft che adatta A D O alla piattaforma .NET; offre un'interfaccia set-oriented e introduce i DataAdapter Soluzione per l'accesso ai dati in Java sviluppata da Sun Microsystems; offre in quel contesto un servizio simile a O D B C

Figura 6.3 Caratteristiche delle soluzioni CLI

6.4.1 ODBC e soluzioni proprietarie Microsoft L a p i a t t a f o r m a s o f t w a r e M i c r o s f t p r e s e n t a u n a certa varietà di soluzioni p e r l ' a c c e s s o alle basi di dati. I l l u s t r i a m o le caratteristiche principali di q u e s t e s o l u z i o n i . ODBC Open DataBase Connectivity ( O D B C ) è u n a i n t e r f a c c i a applicativa proposta o r i g i n a r i a m e n t e dalla M i c r o s o f t e d i v e n t a t a in s e g u i t o u n o s t a n d a r d . O D B C c o s t i t u i s c e il c u o r e d e l l ' a r c h i t e t t u r a per l ' a c c e s s o alle basi di dati d e l l ' a t t u a l e piatt a f o r m a s o f t w a r e M i c r o s o f t . O D B C è u n a s o l u z i o n e m o l t o ricca, s v i l u p p a t a c o n l ' o b i e t t i v o di c o n s e n t i r e l ' a c c e s s o a basi di dati relazionali in un c o n t e s t o e t e r o g e n e o e distribuito. L a d e s c r i z i o n e d e t t a g l i a t a di q u e s t a s o l u z i o n e r i c h i e d e r e b b e m o l to s p a z i o . M e t t e r e m o invece in e v i d e n z a le caratteristiche di f o n d o d e l l a s o l u z i o n e e d e s c r i v e r e m o un m o d o r a p i d o p e r s f r u t t a r e i suoi servizi nella r e a l i z z a z i o n e di u n a a p p l i c a z i o n e c h e f a c c i a a c c e s s o a un D B M S . L ' o b i e t t i v o di O D B C è di p e r m e t t e r e la c o s t r u z i o n e di a p p l i c a z i o n i c h e f a c c i a n o a c c e s s o a basi di dati relazionali di tipo e t e r o g e n e o . O D B C ha i n c o n t r a t o un n o t e v o l e s u c c e s s o ed è s u p p o r t a t a dalla m a g g i o r parte dei p r o d o t t i relazionali. È di gran l u n g a la s o l u z i o n e più significativa per i s i s t e m i W i n d o w s ed e s i s t o n o i m p l e m e n t a z i o n i di e s s a p e r molti altri sistemi operativi ( a n c h e se in questi a m b i e n t i le s o l u z i o n i s o n o c a r a t t e r i z z a t e d a livelli di r o b u s t e z z a e d i f f u s i o n e m o l t o m i n o r i ) . T r a m i t e u n a i n t e r f a c c i a O D B C , le a p p l i c a z i o n i p o s s o n o a c c e d e r e a dati p r e s e n t i su sistemi relazionali g e n e r i c i , e v e n t u a l m e n t e p r e s e n t i su sistemi r e m o t i r a g g i u n gibili t r a m i t e u n a rete; il l i n g u a g g i o s u p p o r t a t o d a O D B C è un S Q L "ristretto", c a r a t t e r i z z a t o cioè d a un i n s i e m e limitato di istruzioni, d e f i n i t o n e l l ' a m b i t o del c o m i t a t o SQL Access Group (S A G ) . N e l l ' a r c h i t e t t u r a O D B C , il c o l l e g a m e n t o tra u n ' a p p l i c a z i o n e e un server ric h i e d e l ' u s o di un driver, u n a libreria c h e v i e n e c o l l e g a t a d i n a m i c a m e n t e alle a p plicazioni e v i e n e d a e s s e invocata. Il driver m a s c h e r a le d i f f e r e n z e di i n t e r a z i o n e legate n o n solo al D B M S , m a a n c h e al s i s t e m a o p e r a t i v o e al p r o t o c o l l o di rete utilizzato. P e r t a n t o , per g a r a n t i r e la c o m p a t i b i l i t à rispetto allo s t a n d a r d O D B C , c i a s c u n v e n d i t o r e deve g a r a n t i r e dei driver c h e p r e v e d a n o l ' u s o del D B M S nell ' a m b i t o di u n a specifica rete e c o n u n o s p e c i f i c o s i s t e m a o p e r a t i v o . Per e s e m p i o , la tripla ( S y b a s e , Windows/NT, Novell) i d e n t i f i c a u n o s p e c i f i c o driver. Il driver così m a s c h e r a tutti i p r o b l e m i d ' i n t e r o p e r a b i l i t à (non solo quelli posti dal D B M S ) , e facilita la scrittura delle a p p l i c a z i o n i . L ' a c c e s s o a u n a b a s e di dati tramite O D B C r i c h i e d e la c o o p e r a z i o n e di q u a t t r o c o m p o n e n t i di sistema. • L applicazione richiama le f u n z i o n i S Q L p e r e s e g u i r e i n t e r r o g a z i o n i e per acq u i s i r n e i risultati. L a scelta del p r o t o c o l l o di c o m u n i c a z i o n e , del server D B M S e del s i s t e m a o p e r a t i v o del n o d o o v e il D B M S è installato s o n o tutti trasparenti per l ' a p p l i c a z i o n e , e s s e n d o m a s c h e r a t i dal driver. • Il driver manager è r e s p o n s a b i l e di c a r i c a r e i driver a richiesta d e l l ' a p p l i c a z i o ne. Q u e s t o s o f t w a r e , f o r n i t o d i r e t t a m e n t e dalla M i c r o s o f t per il m o n d o W i n d o w s , g a r a n t i s c e a n c h e a l c u n e f u n z i o n i p e r gestire c o r r i s p o n d e n z e f r a n o m i e f u n z i o n i di i n i z i a l i z z a z i o n e c h e a s s i c u r a n o il b u o n f u n z i o n a m e n t o dei driver.

• I driver s o n o responsabili di eseguire f u n z i o n i O D B C ; pertanto, s o n o in g r a d o di eseguire interrogazioni in S Q L , t r a d u c e n d o l e in m o d o da adattarsi alla sintassi e alla s e m a n t i c a degli specifici prodotti cui viene fatto accesso. I driver s o n o a n c h e responsabili di restituire i risultati alle applicazioni, tramite m e c c a n i s m i di b u f f e r i n g . • La fonte di i n f o r m a z i o n e (in inglese: data source) è il sistema che e s e g u e le funzioni trasmesse dal client. Le fonti d ' i n f o r m a z i o n e di interesse principale sono i database server relazionali. 1 codici di errore s o n o standardizzati, così da consentire il controllo delle c o n dizioni di errore a t e m p o di e s e c u z i o n e . Le interrogazioni S Q L p o s s o n o e s s e r e specificate in m o d o statico o p p u r e essere incluse in stringhe c h e v e n g o n o g e n e rate ed eseguite d i n a m i c a m e n t e . L ' e s e c u z i o n e p u ò quindi generare degli errori, q u a n d o il c o d i c e S Q L c o n t e n u t o nella stringa non è corretto. O D B C è quindi un m e c c a n i s m o standard che risolve un p r o b l e m a significativo. Data la sua c o m p l e s s i t à non è però adatto a essere utilizzato direttamente dal p r o g r a m m a t o r e per lo s v i l u p p o di applicazioni. A q u e s t o s c o p o M i c r o s o f t h a sviluppato delle soluzioni proprietarie, che s e m p l i f i c a n o la realizzazione di applicazioni che f a n n o accesso ai servizi di u n a base di dati. Q u e s t e soluzioni innalzano il livello di astrazione, s f r u t t a n d o i vantaggi del p a r a d i g m a di p r o g r a m m a z i o n e a oggetti, e s t e n d e n d o inoltre i tipi di sorgenti dati con le quali u n ' a p p l i c a z i o n e p u ò interagire. D e s c r i v i a m o quindi b r e v e m e n t e OLE DB, ADO e ADO.NET.

OLE DB

Object Linking and Embedding far DataBases

(OLE DB) è un'inter-

faccia generale, che permette di a c c e d e r e a sorgenti dati di tipo generico: non solo sistemi relazionali, m a a n c h e u n a vasta tipologia di archivi di dati, c o m e p e r e s e m pio caselle di posta elettronica o sistemi C A D / C A M . O L E D B si b a s a sul m o d e l l o a oggetti C O M , che ricopre un ruolo di p r i m o p i a n o nell'architettura s o f t w a r e M i c r o s o f t . A s e c o n d a delle caratteristiche della sorgente dati usata, sarà o m e n o possibile utilizzare servizi di accesso sofisticati. Per e s e m p i o , se la sorgente dati è una base dati relazionale, cui si f a a c c e s s o utilizzando O D B C , sarà possibile interagire inviando c o m a n d i S Q L da eseguire che p r o d u r r a n n o c o m e risposta insiemi di tupie, cui sarà possibile a c c e d e r e con m e c c a n i s m i di scansione. ADO ActiveX Data Object ( A D O ) costituisce u n ' i n t e r f a c c i a di alto livello ai servizi offerti da O L E D B . Il m o d e l l o di A D O si b a s a sulla definizione di quattro concetti f o n d a m e n t a l i : la c o n n e s s i o n e , il c o m a n d o , la tupia e l ' i n s i e m e di tupie. L a c o n n e s s i o n e ( C o n n e c t i o n ) rappresenta il c a n a l e di c o m u n i c a z i o n e c h e deve essere stabilito per interagire con una sorgente dati, f o r n e n d o la locazione della sorgente dati nel sistema e n o r m a l m e n t e lo u s e r n a m e e la p a s s w o r d da utilizzare per identificarsi sul sistema; un c o m p o n e n t e i m p o r t a n t e della c o n n e s s i o n e è la collezione di errori (Errors), che r a p p r e s e n t a l ' i n s i e m e di a n o m a l i e che si p o s s o n o verificare n e l l ' i n t e r a z i o n e con la sorgente dati; questa struttura viene definita c o m e u n a collezione in q u a n t o si a s s u m e che diverse a n o m a l i e p o s s o n o essere attivate c o n t e m p o r a n e a m e n t e . Il c o m a n d o ( C o m m a n d ) rappresenta la stringa di caratteri c h e

(1) Public Sub InterrogaBD()

(2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) (15) (16)

(17) (18) (19) (20) (21) (22) (23) (24)

Dim Dim Dim Dim Dim Dim Dim

setlmpiegati As ADODB.Recordset conn As ADODB.Connection stringaSQL As String comSQL As ADODB.Command arrlmpiegati As Variant messaggio As String numRighe As Integer

Set conn = New ADODB.Connection conn.Open "mioServer","giovanni","passwordsegreta" Set setlmpiegati = New ADODB.Recordset stringaSQL = "select Nome, Cognome, Data " _ "from Impiegato order by Cognome" comSQL.CommandText = stringaSQL setlmpiegati.Open comSQL, conn, , , Do While Not setlmpiegati.EOF messaggio = "Impiegato: " & setlmpiegati! Nome & setlmpiegati! Cognome & "(record " & _ setlmpiegati.AbsolutePosition & _ " di " & setlmpiegati.RecordCount & ")' If MsgBox(messaggio, vbOkCancel) = vbCancel Then Exit Do setlmpiegati.MoveNext Loop setlmpiegati.Close conn. Close Set setlmpiegati = Nothing Set conn = Nothing

(25) End Sub Figura 6.4 Una procedura Visual Basic che accede a una s o r g e n t e dati ODBC t r a m i t e ADO

contiene l ' i s t r u z i o n e S Q L che si vuole far eseguire sulla sorgente dati. La tupla (.Record) descrive la singola riga di una tabella e o f f r e strumenti per riconoscere la struttura dei dati che c o m p o n g o n o la tupla. L ' i n s i e m e di tuple ( R e c o r d S e t ) definisce la struttura che verrà usata per c o n s e r v a r e i risultati dei c o m a n d i inviati alla sorgente dati; il R e c o r d S e t o f f r e m e c c a n i s m i per scandire l ' i n s i e m e di tuple e accedere a una tupla alla volta, in m o d o a n a l o g o ai cursori. A D O è utilizzabile nei diversi linguaggi di p r o g r a m m a z i o n e utilizzati per lo s v i l u p p o di applicazioni sulla p i a t t a f o r m a M i c r o s o f t W i n d o w s (per e s e m p i o . Visual C + + , Visual Basic, VBscript, Jscript). La Figura 6.4 presenta un e s e m p i o di una p r o c e d u r a Visual Basic che fa uso di A D O .

A n c h e s e n z a c o n o s c e r e il l i n g u a g g i o , d o v r e b b e e s s e r e f a c i l e c o m p r e n d e r e la s t r u t t u r a d e l l a p r o c e d u r a I n t e r r o g a B D in F i g u r a 6 . 4 . N e l l e i s t r u z i o n i ( 2 ) - ( 8 ) si d i c h i a r a n o le v a r i a b i l i c h e v e r r a n n o u s a t e nel p r o g r a m m a . Si o s s e r v a in p a r t i c o l a r e l ' u s o dei tipi R e c o r d s e t , C o n n e c t i o n e C o m m a n d di A D O , c h e v e n g o n o e s p l i c i t a m e n t e estratti dal m o d u l o ADODB. L a p r o c e d u r a i n i z i a l i z z a n e l l e i s t r u z i o n i ( 9 ) e ( 1 0 ) la c o n n e s s i o n e c o n n . Si i n i z i a l i z z a n o q u i n d i l ' i n s i e m e di t u p l e s e t l m p i e g a t i e il c o m a n d o S Q L c h e v e r r à e s e g u i t o s u l l a b a s e di dati. L ' i s t r u z i o n e ( 1 4 ) i n v o c a il m e t o d o o p e n di R e c o r d S e t e q u i n d i c h i e d e l ' e s e c u z i o ne d e l l a q u e r y a s s o c i a t a al c o m a n d o c o m S Q L . 11 p r o g r a m m a e n t r a p o i nel c i c l o d e s c r i t t o d a l l e i s t r u z i o n i ( 1 5 ) - ( 2 0 ) . In q u e s t o c i c l o si s c a n d i s c o n o u n a alla v o l t a ( m e t o d o M o v e N e x t ) le t u p l e del r i s u l t a t o , fino a c h e le t u p l e s o n o t e r m i n a t e ( m e t o d o E O F ) o l ' u t e n t e h a s e l e z i o n a t o il b o t t o n e C a n c e l d e l l a finestra c h e p r e s e n t a i v a l o r i d e l l a t u p l a c o r r e n t e . A l t e r m i n e d e l c i c l o , la p r o c e d u r a r i l a s c i a gli o g g e t t i utilizzati.

ADO.NET

A D O . N E T rappresenta l'evoluzione della soluzione A D O , progettata p e r o p e r a r e a l l ' i n t e r n o d e l l a p i a t t a f o r m a . N E T di M i c r o s o f t . A D O . N E T n o n è u n a s e m p l i c e e s t e n s i o n e di A D O , b e n s ì è il f r u t t o di u n ' a t t i v i t à di r i p r o g e t t a z i o n e c h e trae s p u n t o d a l l e c a r a t t e r i s t i c h e di . N E T . Q u e s t a b r e v e d e s c r i z i o n e h a lo s c o p o di m e t t e r e in e v i d e n z a le c a r a t t e r i s t i c h e di f o n d o di A D O . N E T , s e g n a l a n d o le v a r i a z i o n i r i s p e t t o ad A D O . C o m e al s o l i t o , si r i m a n d a a l l a r i c c a d o c u m e n t a z i o n e d i s p o n i b i l e sul sito d e l l a M i c r o s o f t o a testi s p e c i f i c i s u l l ' a r g o m e n t o p e r a v e r e il livello di d e t t a g l i o c h e c o n s e n t a di s v i l u p p a r e d i r e t t a m e n t e u n ' a p p l i c a z i o n e . L a d i f f e r e n z a di f o n d o tra A D O . N E T e A D O è il d i v e r s o a p p r o c c i o p e r la g e s t i o n e d e l d i a l o g o c o n la b a s e di d a t i . In A D O l ' o g g e t t o c e n t r a l e è il RecordSet, il q u a l e di n o r m a v i e n e g e s t i t o t r a m i t e c o n n e s s i o n i d i r e t t e c o n la b a s e di d a t i . L ' a c c e s s o al RecordSet a v v i e n e p o i c o n m e c c a n i s m i c h e s o n o a n a l o g h i ai c u r s o r i . In A D O . N E T i n v e c e i d a t i v e n g o n o g e s t i t i t r a m i t e i DataSet, i quali costituiscono dei c o n t e n i t o r i di o g g e t t i (tra c u i i DataTable, c h e r a p p r e s e n t a n o le n o r m a l i t a b e l le). A d i f f e r e n z a di A D O , l ' a c c e s s o i n t e r n o agli e l e m e n t i d e i DataSet e DataTable a v v i e n e u t i l i z z a n d o i n o r m a l i m e c c a n i s m i di a c c e s s o a c o l l e z i o n i di o g g e t t i . U n a l t r o a s p e t t o c h e d i s t i n g u e A D O . N E T è c h e u n DataSet p e r m e t t e la g e s t i o ne di r e l a z i o n i e v i n c o l i di i n t e g r i t à tra gli o g g e t t i al s u o i n t e r n o . Q u e s t a flessibilità è r e s a p o s s i b i l e d a l f a t t o c h e i DataSet r a p p r e s e n t a n o s t r u t t u r e c h e r i s i e d o n o p i e n a m e n t e n e l l ' a m b i e n t e d e l p r o g r a m m a , m e n t r e in A D O il risultato di u n a q u e r y v i e n e m a n t e n u t o n e l c o n t e s t o d e l l a s e s s i o n e c o n la b a s e di d a t i e d i v i e n e d i s p o n i bile al p r o g r a m m a t u p l a p e r t u p l a t r a m i t e l ' i n v o c a z i o n e d e i m e t o d i d i a c c e s s o al

RecordSet. In A D O . N E T il c o o r d i n a m e n t o tra i DataSet e le s o r g e n t i dati a v v i e n e t r a m i te c o m p o n e n t i s p e c i f i c i , i DataAdapter. L a c l a s s e DataAdapter presenta diverse s p e c i a l i z z a z i o n i , a s e c o n d a d e l l e c a r a t t e r i s t i c h e d e l l a s o r g e n t e dati ( p e r e s e m p i o , SqlDataAdapter p e r a c c e d e r e a M i c r o s o f t S Q L S e r v e r , OledbDataAdapter per a c c e d e r e a u n a s o r g e n t e O L E D B , OdbcDataAdapter per accedere a una sorgente O D B C ) . I m e t o d i p r i n c i p a l i d e l DataAdapter s o n o il m e t o d o Fili, c h e c a r i c a dati d a l l a s o r g e n t e e li t r a s f e r i s c e nel DataSet, e il m e t o d o Update, c h e i n v e c e

a g g i o r n a lo stato della s o r g e n t e dati r i p o r t a n d o in e s s a le variazioni i n t r o d o t t e sul DataSet. Vi s o n o m o l t e p l i c i v a n t a g g i n e l l ' a t t r i b u i r e ai DcitaAdapter la g e s t i o n e del d i a l o g o con le sorgenti dati: è p o s s i b i l e m i n i m i z z a r e il n u m e r o di c o n n e s sioni c o n t e m p o r a n e a m e n t e attive in un s i s t e m a m u l t i t a s k i n g (in q u a n t o c i a s c u n DataAdapter o c c u p a di n o r m a la c o n n e s s i o n e solo per il t e m p o n e c e s s a r i o p e r e s e g u i r e i m e t o d i Fili e Update)-, è p o s s i b i l e s f r u t t a r e la c o n o s c e n z a d e l l o s c h e m a della b a s e di dati per gestire la c o m u n i c a z i o n e in m o d o più e f f i c i e n t e ; è f a c i l e integrare nello stesso DataSet dati c h e p r o v e n g o n o d a sorgenti diverse. O l t r e a ciò, A D O . N E T è c o e r e n t e a l l ' i m p o s t a z i o n e c o m u n e di . N E T e p e r m e t t e di s c a m biare f a c i l m e n t e oggetti a l l ' i n t e r n o d e l l ' a m b i e n t e .NET, u t i l i z z a n d o X M L c o m e f o r m a t o di r a p p r e s e n t a z i o n e .

6.4.2 Java Database Connectivity (JDBC) J a v a è u n m o d e r n o l i n g u a g g i o di p r o g r a m m a z i o n e , p r o p o s t o dalla S u n M i c r o s y s t e m s , c h e sta riscuotendo un n o t e v o l e s u c c e s s o n e l l o s v i l u p p o di a p p l i c a z i o n i , s o p r a t t u t t o d o v e e s i s t o n o p r o b l e m i significativi di p o r t a b i l i t à e di i n t e g r a z i o n e c o n le reti. S e n z a d e s c r i v e r e il l i n g u a g g i o , c i ò c h e a n d r e b b e b e n al di là degli obiettivi di q u e s t o testo, è p o s s i b i l e f a r e c e n n o alle caratteristiche del l i n g u a g g i o c h e h a n n o c o n t r i b u i t o al s u o s u c c e s s o . Java è u n m o d e r n o l i n g u a g g i o di p r o g r a m m a z i o n e a oggetti, m a il l i n g u a g g i o di p r o g r a m m a z i o n e è solo il c o m p o n e n t e c e n t r a l e di u n a p r o p o s t a m o l t o articolata. L ' a r c h i t e t t u r a p r e v e d e c h e i p r o g r a m m i Java v e n g a n o tradotti in un f o r m a t o c o m p a t t o ( b y t e c o d e ) , e v e n g a n o q u i n d i eseguiti da u n a J a va Virtual M a c h i n e , n o r m a l m e n t e r e a l i z z a t a d a un s i s t e m a s o f t w a r e . P e r e s e g u i r e u n ' a p p l i c a z i o n e Java in un s i s t e m a di c a l c o l o è q u i n d i s u f f i c i e n t e d i s p o r r e di u n a Java Virtual M a c h i n e p e r il p a r t i c o l a r e a m b i e n t e . Visto c h e e s i s t o n o diverse i m p l e m e n t a z i o n i di Java Virtual M a c h i n e per m o l t i diversi a m b i e n t i , u n ' a p p l i c a z i o n e J a v a è in g r a d o di o f f r i r e u n livello di p o r t a b i l i t à m o l t o elevato. Il l i n g u a g g i o , oltre a o f f r i r e tutte le caratteristiche di un m o d e r n o l i n g u a g g i o di p r o g r a m m a z i o n e ( m o d e l l o a oggetti, e c c e z i o n i , m e c c a n i s m i p e r l ' e s e c u z i o n e c o n c o r r e n t e e la s i n c r o n i z z a z i o n e , i n v o c a z i o n e r e m o t a , s i c u r e z z a ecc.), è a r r i c c h i t o d a u n a e s t e s a libreria di m o d u l i c h e o f f r o n o delle s o l u z i o n i i m m e diate e r o b u s t e p e r c o s t r u i r e a p p l i c a z i o n i in tanti diversi contesti. P e r e s e m p i o , il l i n g u a g g i o o f f r e librerie p e r c o s t r u i r e i n t e r f a c c e g r a f i c h e , p e r r e a l i z z a r e servizi di crittografia e s i c u r e z z a e p e r gestire c o n t e n u t i m u l t i m e d i a l i . C i a s c u n o di questi m o d u l i e s p o r t a i suoi servizi a l l ' a m b i e n t e Java t r a m i t e u n ' o p p o r t u n a A p p l i c a t i o n P r o g r a m m i n g I n t e r f a c e . Tra questi m o d u l i , è p r e s e n t e il m o d u l o Java D a t a b a s e C o n n e c t i v i t y ( J D B C ) . J D B C p e r m e t t e a p r o g r a m m i Java di a c c e dere in m o d o u n i f o r m e a basi di dati relazionali, in m o d o simile a q u a n t o o f f e r t o dal p r o t o c o l l o O D B C . L ' a r c h i t e t t u r a p r e v e d e u n o strato, c o s t i t u i t o dal driver m a n a g e r , il q u a l e isola l ' a p p l i c a z i o n e dal c o m p o n e n t e r e s p o n s a b i l e di i m p l e m e n t a r e il s e r v i z i o ( c h e è n o r m a l m e n t e c o s t r u i t o dagli stessi p r o d u t t o r i dei D B M S o d a s v i l u p p a t o r i specializzati di s o f t w a r e ) . Vi s o n o m o l t e p l i c i architetture c h e p o s s o n o e s s e r e utilizzate p e r i m p l e m e n t a r e le f u n z i o n i di a c c e s s o al D B M S ( F i g u r a 6.5):

Type 1

Type 2

Type 3

Type 4

J a v a Application

Java Application

J a v a Application

J a v a Application

J D B C Driver M a n a g e r

J D B C Driver Manager

J D B C Driver M a n a g e r

J D B C Driver M a n a g e r

JDBC/nat ve Bridge

J D B C / O D B C Bridge

JDBC Middleware

J D B C Driver

(Various D B M S s )

( D B M S Specific)

Native driver ( D B M S Specific)

Figura 6.5 Le a r c h i t e t t u r e JDBC

1. Driver nativo: q u e s t a s o l u z i o n e p r e v e d e la r e a l i z z a z i o n e di f u n z i o n i Java c h e c o n v e r t o n o le richieste J D B C in richieste a un driver in c o d i c e nativo d e l l a m a c c h i n a c h e e s e g u e il p r o g r a m m a Java. Il driver è s p e c i f i c o p e r il D B M S cui si v u o l e a c c e d e r e ed è n o r m a l m e n t e un driver r e a l i z z a t o p e r p e r m e t t e r e l ' a c c e s so al D B M S d a parte di a p p l i c a z i o n i scritte nei tradizionali l i n g u a g g i di alto livello. 2. Ponte (in i n g l e s e bridge) JDBC/ODBC: q u e s t a architettura p r e v e d e di tradurre le richieste J D B C in richieste al driver m a n a g e r O D B C . Q u e s t a s o l u z i o ne richiede q u i n d i c h e la m a c c h i n a c h e e s e g u e il c o d i c e J a v a p o s s i e d a u n ' i n s t a l l a z i o n e di O D B C c o n il driver s p e c i f i c o p e r il D B M S cui si v u o l e f a r e accesso. Q u e s t e d u e soluzioni n o n s o n o r e a l m e n t e portabili, p e r c h é richiedono l ' u t i l i z z o di c o m p o n e n t i nativi, c i o è specifici d e l l ' a m b i e n t e in cui v e n g o n o eseguiti. E s s e s o n o d i f f u s e in architetture a p i ù livelli al fine di s f r u t t a r e la d i s p o n i b i l i t à di s t r u m e n t i esistenti. Vi s o n o poi d u e s o l u z i o n i c h e si a p p o g g i a n o su un a m b i e n t e c o m p l e t a m e n t e Java. 3. Middleware-server. q u e s t a s o l u z i o n e p r e v e d e l ' u s o di u n server scritto in J a v a r e s p o n s a b i l e di t r a d u r r e le richieste p r o v e n i e n t i dal driver m a n a g e r nel f o r m a t o r i c o n o s c i u t o dal p a r t i c o l a r e D B M S c h e si i n t e n d e utilizzare. S o n o p r e s e n t i sul m e r c a t o dei prodotti c h e r e a l i z z a n o q u e s t e f u n z i o n i p e r m e t t e n d o di interagire c o n i s i s t e m i relazionali più d i f f u s i .

4. Driver Java: questa soluzione prevede l ' u s o di un driver specifico per il particolare sistema relazionale, in m o d o a n a l o g o ai driver in c o d i c e nativo usati in O D B C . I driver v e n g o n o n o r m a l m e n t e offerti c o m e opzioni dagli stessi produttori dei sistemi relazionali. J D B C rappresenta una s o l u z i o n e m o l t o interessante per la realizzazione di applicazioni portabili che f a c c i a n o accesso a basi di dati. Per utilizzare i servizi di J D B C n o r m a l m e n t e si s e g u o n o i passi seguenti: 1. 2. 3. 4.

si si si si

carica il driver richiesto; crea una c o n n e s s i o n e con la base di dati; c o m p o n e il c o m a n d o S Q L e lo si invia alla base di dati; gestisce il risultato del c o m a n d o S Q L .

M o s t r i a m o l ' u s o di J D B C con un s e m p l i c e e s e m p i o , che a p p a r e in Figura 6.6. La p r i m a istruzione specifica la posizione n e l l ' a l b e r o delle classi Java delle classi

(1) import java.sql.*; (2) public class PrimoJdbc { (3) public static void main(String[] arg) { (4) Connection conn = null; (5) try { (6) // Caricamento del driver (7) Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); (8) // Apertura della connessione (9) conn = DriverManager.getConnection( (10) " jdbc: odbc: Corsi" ) ; (11)

}

(12) (13) (14) (15) (16) (17) (18) (19) (20) (21) (22) (23) (24) (25) (26) (27)

catch (Exception e) { System.exit(1); } try { // Esecuzione dell'interrogazione Statement interrogazione = conn. createStatement ( ) ; ResultSet risultato = interrogazione.executeQuery( "select * from Corsi"); while (risultato.next()) { String nomeCorso = risultato.getString("NomeCorso"); System.out.println(nomeCorso); } } catch (Exception e) { System.exit(1); }

(28)

} }

Figura 6.6 Una classe Java che accede a una s o r g e n t e dati JDBC t r a m i t e un bridge JDBC-ODBC

che realizzano i servizi J D B C , i quali si trovano nel sottoalbero s q l d e l l ' a l b e r o j a v a che contiene i servizi di base del sistema. La c o n n e s s i o n e viene gestita con un oggetto c o n n della classe C o n n e c t i o n , c h e viene inizializzato a n u l i . L'istruzione alla linea (7) specifica il driver che deve essere caricato ( t r a s c u r i a m o i dettagli); in q u e s t o c a s o il driver è di tipo 2 e si a p p o g g i a a una s o l u z i o n e O D B C sottostante. N e l l ' i s t r u z i o n e alle linee (9-10) viene e f f e t t i v a m e n t e stabilita la c o n nessione con la base di dati, s f r u t t a n d o il m e t o d o g e t C o n n e c t i o n della classe D r i v e r M a n a g e r , cui viene passato c o m e p a r a m e t r o l'identificativo della base di dati (deve essere stata preventivamente creata la sorgente dati O D B C " C o r s i " ) . In c a s o di errori in una di queste istruzioni, il sistema g e n e r e r à u n ' e c c e z i o n e che terminerà l ' e s e c u z i o n e del p r o g r a m m a (istruzione S y s t e m . e x i t ( 1 ) alla linea (12)). U n a volta che la c o n n e s s i o n e è stata stabilita, è possibile inviare c o m a n di S Q L alla base di dati. N e l l ' i s t r u z i o n e alle linee (15-16) viene creato l ' o g g e t t o i n t e r r o g a z i o n e a p p a r t e n e n t e alla classe S t a t e m e n t , associato alla c o n nessione c o n n . 11 m e t o d o e x e c u t e Q u e r y o f f e r t o dalla classe S t a t e m e n t viene invocato su i n t e r r o g a z i o n e , f o r n e n d o c o m e p a r a m e t r o il testo della query S Q L di cui si richiede l ' e s e c u z i o n e i m m e d i a t a . L ' e s e c u z i o n e del c o m a n d o p r o d u c e un insieme di tuple c h e v e n g o n o assegnate a l l ' o g g e t t o r i s u l t a t o della classe R e s u l t S e t . Q u e s t a classe o f f r e servizi analoghi a quelli dei cursori, che p e r m e t t o n o di scandire l ' i n s i e m e di tuple e considerarle una alla volta. In ogni istante esiste in R e s u l t S e t una tupla corrente (all'inizio sarà la p r i m a ) e il m e t o d o n e x t permette di rendere tupla corrente la tupla successiva. Il m e t o d o g e t s t r i n g estrae dalla tupla corrente l'attributo il cui n o m e viene passato come p a r a m e t r o al m e t o d o (in q u e s t o c a s o N o m e C o r s o ) ; g e t s t r i n g a s s u m e c h e l'attributo abbia un valore rappresentabile c o m e stringa di caratteri; vi sono diversi altri m e t o d i specifici per ciascun d o m i n i o (per e s e m p i o , g e t l n t , g e t F l o a t , g e t D a t e ecc.). Il ciclo w h i l e scandirà quindi il c o n t e n u t o di r i s u l t a t o fino a che il m e t o d o n e x t ( ) non restituirà il valore b o o l e a n o falso.

Note bibliografiche SQL Embedded fa parte dello standard SQL-2 e quindi si può far riferimento alla versione ufficiale dello standard SQL o ai numerosi libri divulgativi dedicati a SQL, tra i quali il libro di Cannan e Otten [12] (di cui esiste la traduzione italiana) e i libri di Melton e Simon [48, 49], I documenti di specifica delle diverse soluzioni CLI sono facilmente accessibili in rete. Sul sito Web della Microsoft sono disponibili i documenti di specifica di ODBC, OLE DB, A D O e ADO.NET. Il sito della Sun dedicato a Java ospita invece le diverse versioni della specifica JDBC. In ciascuno dei siti è inoltre disponibile un insieme di manuali d'uso e spesso di tutorial sugli specifici strumenti. Per quanto riguarda le estensioni procedurali di SQL conviene fare riferimento ai manuali dei diversi sistemi. Sono poi disponibili su questi argomenti numerosi libri, dedicati al vasto pubblico dei professionisti dell'informatica.

Esercizi 6.1

Si supponga di avere le tabelle: MAGAZZINO(Prodotto, QtaDisp,Soglia,QtaRiordino) ORDINEINCORSO(Prodotto,Qta) Scrivere una procedura SQL che realizza il prelievo dal magazzino accettando due parametri, il prodotto Prode la quantità' da prelevare QtaPrelievo. La procedura deve verificare inizialmente che QtaPrelievo sia inferiore al valore di QtaDisp per il prodotto indicato. QtaPrelievo viene quindi sottratta al valore di QtaDisp. A questo punto la procedura verifica se per il prodotto QtaDisp risulta minore di Soglia, senza che in ORDINEINCORSO compaia già una tupla relativa al prodotto prelevato; se sì, viene inserito un nuovo elemento nella tabella ORDINEINCORSO, con i valori di Prod e del corrispondente attributo QtaRiordino.

6.2

Realizzare una procedura in un linguaggio di programmazione di alto livello che tramite SQL Embedded elimina dalla tabella DIPARTIMENTO l'elemento che ha il nome che viene fornito come parametro alla procedura.

6.3

Realizzare un programma in un linguaggio di programmazione di alto livello che tramite SQL Embedded costruisce una videata in cui si presentano le caratteristiche di ogni dipartimento seguito dall'elenco degli impiegati che lavorano nel diartimento, ordinati per cognome.

6.4

Realizzare l'esercizio precedente usando ADO.

6.5

Realizzare un programma Java che scandisce gli impiegati ordinati per cognome e inserisce ogni impiegato che si trova in una posizione che è un multiplo di 10 in una tabella IMPIEGATIESTRATTL

6.6

Realizzare un programma che accede al contenuto di una tabella CAPITQLQ(Numero,Titolo,Lunghezza) che descrive i capitoli di un libro, con il titolo e la dimensione in pagine. Il programma quindi popola una tabella k INDICE (Numero, Titolo,NumPagine) in cui si presenta il numero di pagina nel quale inizia ogni capitolo, supponendo che il Capitolo 1 inizi sulla prima pagina e che i capitoli debbano iniziare su pagine dispari (eventualmente introducendo una pagina bianca alla fine del capitolo).

6.7

Si faccia riferimento al seguente schema relazionale: IMPIEGATI(CodkeFiscale, Cognome, Nome, DataNascita, Dipartimento, Stipendio); DIPARTIMENTK Codice, Nome, Sede) PROGETTI (Sigla, Titolo, Valore) PARTECIPAZIONEflmpiegato, Progetto. Data) con vincoli di integrità referenziale tra Dipartimento di Impiegati e la relazione DIPARTIMENTI, Progetto di Partecipazione e la relazione PROGETTI e tra Impiegato di Partecipazione e la relazione IMPIEGATI. Scrivere un metodo Java con JDBC (o un frammento di programma in SQL immerso in un linguaggio o pseudolinguaggio di programmazione) che inserisca un impiegato con tutti i dati (letti da input o passati come parametri), verifi-

cando l'esistenza del dipartimento, con rifiuto dell'operazione in caso negativo. Assumere, per semplicità, che il sistema non supporti i vincoli di riferimento. 6.8

Dato lo schema relazionale seguente: IMPIEGATKCodice, Dati, Telefono) con vincolo di integrità referenziale tra Dati e la relazione DATIIMPIEGATO; DATIIMPIEGATO(CodiceDati, Cognome, Nome), definire il metodo Java (o un frammento di programma in SQL immerso in un linguaggio o pseudolinguaggio di programmazione) getlmpiegatoPerNome(String nome) che, dato il nome di un impiegato, restituisce un Oggetto Impiegato in cui i campi (Codice, Nome, Cognome, Telefono) sono opportunamente valorizzati.

6.9

Si consideri il seguente schema relazionale (con gli evidenti vincoli di integrità referenziale): VENDITORE(CodArticolo, CodNegozio, CFCliente, Data, Quantità) ARTICOLl(CodArticolo, Descrizione, CodMarca, CodCategoria, Prezzo) CLIENTE(CFCIiente, Cognome, Nome, Età) NEGOZIO(CodNegozio, Nome, Indirizzo, Città, Provincia, Regione) MARCA(CodMarca, Nome, CodNazione, Nazione) CATEGORlA(CodCateqoria, Descrizione) Scrivere un metodo Java con JDBC che inserisca un nuovo negozio con codice, nome, indirizzo e città (letti da input o passati come parametri), prelevando provincia e regione da altre della stessa tabella (nell'ipotesi che, fissata la città, provincia e regione siano univocamente determinate) e segnalando come errore (o eccezione) il caso in cui i dati sulla città non siano disponibili.

6.10 Con riferimento allo schema relazionale seguente: FARMACI(Codice, NomeFarmaco, PrincipioAttivo, Produttore, Prezzo) con vincolo di integrità referenziale fra Produttore e la relazione PRODUTTORI e fra PrincipioAttivo e la relazione SOSTANZE PRODUTTORI(CodProduttore, Nome, Nazione) SOSTANZE(ID, NomeSostanza, Categoria) scrivere un metodo Java con JDBC che (supponendo già disponibile una connessione, passata come parametro) stampi un prospetto con tutti i farmaci, organizzati per produttore:

CodProduttore Nome Nazione CodiceFarmaco NomeFarmaco Prezzo Sostanza CodiceFarmaco NomeFarmaco Prezzo Sostanza CodProduttore Nome Nazione 6.11 Si consideri una base di dati che contiene informazioni sugli impiegati, ¡ progetti e le sedi di una azienda, con le partecipazioni degli impiegati ai progetti e le sedi di svolgimento dei progetti stessi; essa contiene le seguenti relazioni: IMPIEGATI (Matricola, Cognome, Nome,Progetto), con vincolo di integrità referenziale fra Progetto e la relazione PROGETTI PROGETTI(Codice,Titolo) SEDI(Nome,Città,Indirizzo) SVOLGlMENTO(Progetto.Sede), con vincoli di integrità referenziale fra Progetto e la relazione PROGETTI fra Sede e la relazione SEDI.

Formulare in Java-JDBC (o con SQL immerso in un l i n g u a g g i o o p s e u d o l i n g u a g gio di programmazione), una classe (o un f r a m m e n t o di p r o g r a m m a ) che stampa tutti i progetti (con codice e titolo) e, per ciascuno di essi, gli impiegati coinvolti (mostrando matricola e cognome); in sostanza, va p r o d o t t o un prospetto del t i p o seguente:

CodProgetto TitoloProgetto Matricolalmpiegato Cognomelmpiegato Matricolalmpiegato Cognomelmpiegato CodProgetto TitoloProgetto Matricolalmpiegato Cognomelmpiegato 6.12 Estendere la risposta al quesito precedente mostrando anche, per ciascun progetto, la lista delle sedi di svolgimento, costruendo quindi un prospetto come il seguente: CodProgetto TitoloProgetto Matricolalmpiegato Cognomelmpiegato Matricolalmpiegato Cognomelmpiegato NomeSede NomeSede CodProgetto

Città Città TitoloProgetto

6.13 Si ha uno schema di tabella lmpiegato(Nome, Indirizzo, Capo), in cui l'attributo Capo rappresenta il nome del superiore dell'Impiegato, descritto a sua volta nella tabella. Definire il metodo Java in SQL immerso in un linguaggio o pseudolinguaggio di programmazione) setCapo(lmpiegato ¡1, Impiegato ¡2) che memorizza la relazione tra capo e sottoposto esistente tra due impiegati rifiutando l'inserimento se la relazione è già rappresentata nella tabella. Supporre che gli oggetti Impiegato abbiano una variabile di istanza per ogni campo della corrispondente colonna nello schema relazionale con opportuna corrispondenza di tipi.

Parte second Progettazione di basi di dati

Metodologie e modelli per il progetto

Nei capitoli precedenti sono state analizzate le modalità di descrizione (modelli) e manipolazione (linguaggi) di una base di dati, supponendo che la base di dati con la quale interagire esistesse già. Incominceremo adesso ad affrontare il problema che esiste a monte, quello di progettare una base di dati a partire dai suoi requisiti. Progettare una base di dati significa definirne struttura, caratteristiche e contenuto. Si tratta, come è facile immaginare, di un processo nel quale bisogna prendere molte decisioni delicate e l'uso di opportune metodologie è indispensabile per la realizzazione di un prodotto di alta qualità. In questo capitolo introduttivo, affrontiamo il problema della progettazione di basi di dati da un punto di vista generale e proponiamo alcuni strumenti di lavoro. In particolare, forniremo, nel Paragrafo 7.1, un inquadramento generale nel contesto dello sviluppo dei sistemi informativi e presenteremo una metodologia di progettazione che si è largamente diffusa nell'ambito delle basi di dati. Nel Paragrafo 7.2 illustreremo invece il modello Entità-Relazione, che fornisce al progettista un valido strumento per produrre una rappresentazione dei dati, detta schema concettuale, sulla quale l'intera metodologia si fonda. La metodologia di riferimento è articolata in tre fasi: la progettazione concettuale, la progettazione logica e la progettazione fisica. Ognuna di queste fasi verrà presentata in dettaglio nei capitoli successivi a questo. La seconda parte del libro verrà completata da un capitolo che descrive la normalizzazione, una importante tecnica di analisi di qualità per schemi di basi di dati.

7.1 Introduzione alla progettazione 7.1.1 II ciclo di vita dei sistemi informativi La p r o g e t t a z i o n e di una base di dati costituisce solo una delle c o m p o n e n t i del p r o c e s s o di s v i l u p p o di un sistema i n f o r m a t i v o c o m p l e s s o e va quindi i n q u a d r a t a in un c o n t e s t o più a m p i o , quello del ciclo di vita dei sistemi informativi. C o m e descritto in F i g u r a 7.1, il ciclo di vita di un sistema i n f o r m a t i v o c o m prende, g e n e r a l m e n t e , le seguenti attività. • S t u d i o di fattibilità. Serve a definire, in m a n i e r a per q u a n t o possibile precisa, i costi delle varie alternative possibili e a stabilire le priorità di realizzazione delle varie c o m p o n e n t i del sistema. • R a c c o l t a e analisi dei requisiti. C o n s i s t e nella individuazione e nello studio delle proprietà e delle f u n z i o n a l i t à che il sistema informativo d o v r à avere. Q u e -









sta f a s e richiede una interazione con gli utenti del sistema e p r o d u c e u n a descriz i o n e c o m p l e t a , m a g e n e r a l m e n t e i n f o r m a l e , dei dati coinvolti (anche in termini di previsione sul carico applicativo) e delle operazioni su di essi (anche in termini di previsione sulla loro f r e q u e n z a ) . Vengono inoltre stabiliti i requisiti s o f t w a r e e h a r d w a r e del sistema informativo. Progettazione. Si divide g e n e r a l m e n t e in progettazione dei dati e progettazione delle applicazioni. Nella p r i m a si individua la struttura e l ' o r g a n i z z a z i o n e che i dati d o v r a n n o avere, nell'altra si d e f i n i s c o n o le caratteristiche dei p r o g r a m m i applicativi. Le d u e attività s o n o c o m p l e m e n t a r i e p o s s o n o p r o c e d e r e in parallelo o in cascata. Le descrizioni dei dati e delle applicazioni prodotte in q u e s t a fase s o n o formali e f a n n o r i f e r i m e n t o a specifici modelli. I m p l e m e n t a z i o n e . Consiste nella realizzazione del sistema informativo second o la struttura e le caratteristiche definite nella fase di progettazione. Viene costruita e popolata la base di dati e viene p r o d o t t o il codice dei p r o g r a m m i . Validazione e collaudo. Serve a verificare il corretto f u n z i o n a m e n t o e la q u a lità del sistema informativo. La s p e r i m e n t a z i o n e deve prevedere, per q u a n t o possibile, tutte le condizioni operative. F u n z i o n a m e n t o . In questa fase il sistema i n f o r m a t i v o diventa operativo ed esegue i compiti per i quali era stato o r i g i n a r i a m e n t e progettato. Se non si verificano m a l f u n z i o n a m e n t i o revisioni delle f u n z i o n a l i t à del sistema, questa attività richiede solo operazioni di gestione e m a n u t e n z i o n e .

Va precisato che, c o m e indicato g r a f i c a m e n t e in F i g u r a 7.1, il p r o c e s s o non è quasi mai strettamente sequenziale in q u a n t o spesso, durante l ' e s e c u z i o n e di una delle attività citate, b i s o g n a rivedere decisioni prese nell'attività precedente. Q u e l l o che si ottiene è proprio un " c i c l o " di operazioni. Inoltre, si a g g i u n g e talvolta alle attività citate quella di prototipizzazione, che consiste n e l l ' u s o di specifici strumenti s o f t w a r e per la realizzazione rapida di una versione semplificata del sistema informativo, con la quale sperimentare le sue funzionalità. L a verifica del prototipo p u ò portare a una m o d i f i c a dei requisiti e u n a eventuale revisione del progetto. Le basi di dati costituiscono in effetti solo una delle c o m p o n e n t i di un sistema i n f o r m a t i v o che t i p i c a m e n t e include a n c h e i p r o g r a m m i applicativi, le interfacce con l ' u t e n t e e altri p r o g r a m m i di servizio. C o m u n q u e , il r u o l o centrale che i dati h a n n o in un sistema i n f o r m a t i v o giustifica a m p i a m e n t e u n o studio a u t o n o m o relativo alla progettazione delle basi di dati. Ci i n t e r e s s e r e m o p e r c i ò solo agli aspetti dello s v i l u p p o dei sistemi informativi che riguardano da vicino il progetto delle basi di dati, r i m a n d a n d o a testi s u l l ' i n g e g n e r i a del s o f t w a r e lo studio di tutte le altre attività connesse. In particolare, f o c a l i z z e r e m o la nostra attenzione sulla terza fase del ciclo di vita riportato in F i g u r a 7.1, f a c e n d o riferimento alla progettazione dei dati e d i s c u t e n d o a n c h e alcuni aspetti della relativa attività di raccolta e analisi dei requisiti che la precede. Q u e s t a m a n i e r a di p r o c e d e r e è peraltro c o e rente con l ' a p p r o c c i o allo s v i l u p p o dei sistemi informativi basato sui dati, in cui I attenzione è centrata sui dati e sulle loro proprietà. Q u e s t o a p p r o c c i o prevede p r i m a la progettazione della base di dati e, successivamente, la realizzazione delle applicazioni che la utilizzano.

F i g u r a 7.1 Ciclo di v i t a di u n s i s t e m a i n f o r m a t i v o

7.1.2 Metodologie di progettazione e basi di dati Un a s p e t t o c h e vale la p e n a di p r e c i s a r e è c h e c o s a si i n t e n d e p e r metodologia di progettazione e quali s o n o le p r o p r i e t à c h e u n a m e t o d o l o g i a d e v e g a r a n t i r e . In b u o n a s o s t a n z a , u n a m e t o d o l o g i a di p r o g e t t a z i o n e c o n s i s t e in: • u n a decomposizione d e l l ' i n t e r a attività di p r o g e t t o in passi s u c c e s s i v i i n d i p e n d e n t i tra loro; • u n a serie di strategie d a s e g u i r e nei vari passi e alcuni criteri per la scelta in c a s o di alternative;

• alcuni modelli fasi.

di riferimento

per descrivere i dati di ingresso e uscita delle varie

Le proprietà che una m e t o d o l o g i a deve garantire s o n o principalmente: • la generalità rispetto alle applicazioni e ai sistemi in g i o c o (e quindi la possibilità di utilizzo i n d i p e n d e n t e m e n t e dal p r o b l e m a allo studio e dagli strumenti a disposizione); • la qualità del prodotto in termini di correttezza, c o m p l e t e z z a ed efficienza rispetto alle risorse impiegate; • la facilità d'uso sia delle strategie che dei modelli di riferimento. N e l l ' a m b i t o delle basi di dati, si è consolidata negli anni una m e t o d o l o g i a di progetto che h a dato prova di soddisfare p i e n a m e n t e le proprietà descritte. Tale m e todologia è articolata in tre fasi principali da effettuare in cascata (Figura 7.2) e si f o n d a su un principio d e l l ' i n g e g n e r i a s e m p l i c e m a m o l t o efficace: separare in m a niera netta le decisioni relative a " c o s a " r a p p r e s e n t a r e in u n a b a s e di dati ( p r i m a fase), da quelle relative a " c o m e " farlo (seconda e terza fase). • P r o g e t t a z i o n e concettuale. Il suo s c o p o è quello di rappresentare le specifiche informali della realtà di interesse in termini di una descrizione f o r m a l e e c o m p l e t a , m a i n d i p e n d e n t e dai criteri di r a p p r e s e n t a z i o n e utilizzati nei sistemi di gestione di basi di dati. Il p r o d o t t o di questa fase viene c h i a m a t o schema concettuale e f a r i f e r i m e n t o a un modello concettuale dei dati. C o m e a b b i a m o a c c e n n a t o nel P a r a g r a f o 1.3, i modelli concettuali ci c o n s e n t o n o di descrivere l ' o r g a n i z z a z i o n e dei dati a un alto livello di astrazione, senza tenere c o n t o degli aspetti implementativi. In questa fase infatti, il progettista deve cercare di rappresentare il contenuto informativo della base di dati, senza p r e o c c u p a r si né delle modalità con le quali queste i n f o r m a z i o n i v e r r a n n o codificate in un sistema reale, né d e l l ' e f f i c i e n z a dei p r o g r a m m i che f a r a n n o uso di queste informazioni. • P r o g e t t a z i o n e logica. C o n s i s t e nella traduzione dello s c h e m a concettuale definito nella fase precedente, in termini del m o d e l l o di r a p p r e s e n t a z i o n e dei dati adottato dal sistema di gestione di base di dati a disposizione. 11 p r o d o t t o di questa fase viene d e n o m i n a t o schema logico della base di dati e f a riferimento a un modello logico dei dati. C o m e noto, un m o d e l l o logico ci c o n s e n t e di descrivere i dati s e c o n d o u n a r a p p r e s e n t a z i o n e a n c o r a i n d i p e n d e n t e da dettagli fisici, m a c o n c r e t a perché disponibile nei sistemi di gestione di base di dati. In questa fase, le scelte progettuali si basano, tra l'altro, su criteri di o t t i m i z z a z i o n e delle operazioni da e f f e t t u a r e sui dati. Si f a c o m u n e m e n t e uso a n c h e di tecniche f o r m a l i di verifica della qualità dello s c h e m a logico ottenuto. N e l caso del m o d e l l o relazionale dei dati, la tecnica c o m u n e m e n t e utilizzata è quella della

normalizzazione. • P r o g e t t a z i o n e fisica. In questa f a s e lo s c h e m a logico viene c o m p l e t a t o c o n la specifica dei p a r a m e t r i fisici di m e m o r i z z a z i o n e dei dati (organizzazione dei file e degli indici). Il p r o d o t t o di questa fase viene d e n o m i n a t o schema fisico e f a r i f e r i m e n t o a un modello fisico dei dati. Tale m o d e l l o d i p e n d e dallo specifico

Progettazione di basi di dati

SCHEMA FISICO

(Prodotti della progettazione) Figura 7.2 Le fasi d e l l a p r o g e t t a z i o n e di u n a b a s e di d a t i

sistema di gestione di basi di dati scelto e si basa sui criteri di o r g a n i z z a z i o n e fisica dei dati in quel sistema. V e d i a m o ora in che m a n i e r a i requisiti della base di dati v e n g o n o utilizzati nelle varie fasi della progettazione. È bene qui fare una distinzione tra specifiche sui dati, che r i g u a r d a n o il c o n t e n u t o della base di dati, e specifiche sulle operazioni, che r i g u a r d a n o l ' u s o che utenti e applicazioni f a n n o della base di dati. N e l l a

p r o g e t t a z i o n e c o n c e t t u a l e si fa u s o s o p r a t t u t t o d e l l e s p e c i f i c h e sui dati m e n t r e le s p e c i f i c h e sulle o p e r a z i o n i s e r v o n o solo a verificare c h e lo s c h e m a c o n c e t t u a l e sia c o m p l e t o , c o n t e n g a c i o è le i n f o r m a z i o n i n e c e s s a r i e per e s e g u i r e tutte le o p e r a z i o ni previste. N e l l a p r o g e t t a z i o n e l o g i c a lo s c h e m a c o n c e t t u a l e in i n g r e s s o r i a s s u m e le s p e c i f i c h e sui dati, m e n t r e le s p e c i f i c h e sulle o p e r a z i o n i si utilizzano, i n s i e m e alle previsioni sul c a r i c o applicativo, p e r o t t e n e r e u n o s c h e m a l o g i c o c h e r e n d a tali o p e r a z i o n i eseguibili in m a n i e r a efficiente. In q u e s t a f a s e b i s o g n a a n c h e c o n o s c e r e il m o d e l l o l o g i c o a d o t t a t o m a n o n è a n c o r a n e c e s s a r i o c o n o s c e r e il partic o l a r e D B M S scelto (solo la c a t e g o r i a cui a p p a r t i e n e ) . Infine, nella p r o g e t t a z i o n e fisica si f a u s o d e l l o s c h e m a l o g i c o e delle s p e c i f i c h e sulle o p e r a z i o n i per o t t i m i z zare le p r e s t a z i o n i del s i s t e m a . In q u e s t a f a s e b i s o g n a a n c h e t e n e r e c o n t o delle caratteristiche del p a r t i c o l a r e s i s t e m a di g e s t i o n e di basi di dati utilizzato. Il risultato della p r o g e t t a z i o n e di u n a b a s e di dati n o n è solo lo s c h e m a fisico, m a è costituito a n c h e d a l l o s c h e m a c o n c e t t u a l e e d a l l o s c h e m a l o g i c o . L o s c h e m a c o n c e t t u a l e f o r n i s c e infatti u n a r a p p r e s e n t a z i o n e della b a s e di dati di alto livello, c h e p u ò e s s e r e m o l t o utile a s c o p o d o c u m e n t a t i v o , m e n t r e lo s c h e m a l o g i c o f o r nisce u n a d e s c r i z i o n e c o n c r e t a del c o n t e n u t o della b a s e di dati che, p r e s c i n d e n d o dagli aspetti i m p l e m e n t a t i v i , è il r i f e r i m e n t o per le o p e r a z i o n i di i n t e r r o g a z i o n e e aggiornamento. In F i g u r a 7.3 v e n g o n o m o s t r a t i i p r o d o t t i delle varie fasi nel c a s o d e l l a p r o g e t t a z i o n e di u n a b a s e di dati r e l a z i o n a l e b a s a t a s u l l ' u s o del più d i f f u s o m o d e l l o c o n c e t t u a l e dei dati, il m o d e l l o E n t i t à - R e l a z i o n e . A partire d a requisiti r a p p r e s e n tati d a d o c u m e n t i e m o d u l i di vario g e n e r e , acquisiti a n c h e attraverso l ' i n t e r a z i o n e c o n gli utenti, v i e n e c o s t r u i t o u n o s c h e m a E n t i t à - R e l a z i o n e ( r a p p r e s e n t a t o d a u n d i a g r a m m a ) c h e d e s c r i v e a livello c o n c e t t u a l e la b a s e di dati. Q u e s t a r a p p r e s e n t a z i o n e v i e n e poi t r a d o t t a in u n o s c h e m a r e l a z i o n a l e , costituito da u n a c o l l e z i o n e di tabelle. Infine, i dati v e n g o n o descritti d a u n p u n t o di vista fisico (tipo e dim e n s i o n i dei c a m p i ) e v e n g o n o specificate strutture ausiliarie, c o m e gli indici, per l ' a c c e s s o e f f i c i e n t e ai dati. N e i p r o s s i m i capitoli a f f r o n t e r e m o in m a n i e r a d e t t a g l i a t a i vari passi d e l l a p r o g e t t a z i o n e di basi di dati s e c o n d o la d e c o m p o s i z i o n e di F i g u r a 7 . 2 e c o n rifer i m e n t o ai m o d e l l i usati nella F i g u r a 7.3. P r i m a di c o m i n c i a r e p r e s e n t e r e m o , nel p r o s s i m o p a r a g r a f o , il m o d e l l o E n t i t à - R e l a z i o n e , c h e si è o r m a i a f f e r m a t o c o m e s t a n d a r d di riferimento nelle m e t o d o l o g i e di p r o g e t t o di basi di dati e negli strum e n t i di ausilio alla p r o g e t t a z i o n e di sistemi i n f o r m a t i v i . L a f a s e di p r o g e t t a z i o n e c o n c e t t u a l e c h e d i s c u t e r e m o nel p r o s s i m o c a p i t o l o si f o n d a su q u e s t o m o d e l l o c o n c e t t u a l e . T r a t t e r e m o s u c c e s s i v a m e n t e la p r o g e t t a z i o n e l o g i c a c o n r i f e r i m e n t o al m o d e l l o r e l a z i o n a l e c h e r i m a n e a t u t t ' o g g i il m o d e l l o dei dati più d i f f u s o nei sistemi di g e s t i o n e di basi di dati.

7.2 II modello Entità-Relazione 11 m o d e l l o E n t i t à - R e l a z i o n e (nel seguito u t i l i z z e r e m o s p e s s o per q u e s t o t e r m i n e 1 a b b r e v i a z i o n e E - R ) è un m o d e l l o concettuale di dati e, c o m e tale, f o r n i s c e u n a

Progettazione concettuale

o

'SS?

4L

Progettazione logica

4

Progettazione fisica



—*•

F i g u r a 7 . 3 I p r o d o t t i d e l l e v a r i e fasi d e l p r o g e t t o di u n a b a s e di d a t i r e l a z i o n a l e c o n il m o d e l l o E n t i t à - R e l a z i o n e

serie di strutture, dette costrutti, atte a d e s c r i v e r e la realtà di i n t e r e s s e in u n a m a niera facile d a c o m p r e n d e r e e c h e p r e s c i n d e dai criteri di o r g a n i z z a z i o n e dei dati nei calcolatori. Questi costrutti v e n g o n o utilizzati per d e f i n i r e schemi c h e d e s c n -

v o n o l ' o r g a n i z z a z i o n e e la s t r u t t u r a d e l l e occorrenze1 dei d a t i , o v v e r o , dei valori a s s u n t i dai d a t i al v a r i a r e d e l t e m p o . N e l l a t a b e l l a in F i g u r a 7 . 4 v e n g o n o e l e n c a t i tutti i c o s t r u t t i c h e il m o d e l l o E - R m e t t e a d i s p o s i z i o n e : si p u ò o s s e r v a r e c h e , p e r ogni costrutto, esiste una relativa rappresentazione grafica. C o m e v e d r e m o , questa r a p p r e s e n t a z i o n e ci c o n s e n t e di d e f i n i r e u n o s c h e m a E - R m e d i a n t e un d i a g r a m m a che ne semplifica l'interpretazione.

7.2.1 I costrutti principali del modello C o m i n c i a m o ad a n a l i z z a r e i c o s t r u t t i p r i n c i p a l i di q u e s t o m o d e l l o : le e n t i t à , le r e l a z i o n i e gli attributi.

Entità R a p p r e s e n t a n o c l a s s i di o g g e t t i (fatti, c o s e , p e r s o n e , p e r e s e m p i o ) c h e h a n n o p r o p r i e t à c o m u n i e d e s i s t e n z a " a u t o n o m a " ai fini d e l l ' a p p l i c a z i o n e di i n t e resse: CITTÀ, DIPARTIMENTO, IMPIEGATO, ACQUISTO e VENDITA s o n o e s e m p i

di e n t i t à di u n ' a p p l i c a z i o n e a z i e n d a l e . U n a o c c o r r e n z a di u n ' e n t i t à è u n o g g e t t o d e l l a c l a s s e c h e l ' e n t i t à r a p p r e s e n t a . L e c i t t à di R o m a , M i l a n o e P a l e r m o s o n o e s e m p i di o c c o r r e n z e d e l l ' e n t i t à C I T T À , gli i m p i e g a t i M a r i n i e F e r r a r i s o n o i n v e c e e s e m p i di o c c o r r e n z e d e l l ' e n t i t à IMPIEGATO. Si o s s e r v i c h e u n a o c c o r r e n z a di e n t i t à n o n è u n v a l o r e c h e i d e n t i f i c a u n o g g e t t o ( p e r e s e m p i o , il c o g n o m e d e l l ' i m p i e g a t o o il s u o c o d i c e fiscale) m a è l ' o g g e t t o s t e s s o ( l ' i m p i e g a t o " i n c a r n e e o s s a " ) . U n a i n t e r e s s a n t e c o n s e g u e n z a di q u e s t o f a t t o è c h e u n a o c c o r r e n z a di e n t i t à h a u n ' e s i s t e n z a (e u n ' i d e n t i t à ) i n d i p e n d e n t e d a l l e p r o p r i e t à a e s s o a s s o c i a t e ( u n i m p i e g a t o e s i s t e i n d i p e n d e n t e m e n t e d a l f a t t o di a v e r e u n n o m e , u n c o g n o m e , u n a e t à e c c . ) . In q u e s t o il m o d e l l o E - R p r e s e n t a u n a m a r c a t a d i f f e r e n z a rispetto al m o d e l l o r e l a z i o n a l e n e l q u a l e , c o m e a b b i a m o v i s t o nel C a p i t o l o 2, n o n p o s s i a m o rappresentare un oggetto senza conoscere alcune sue proprietà (un impiegato v i e n e r a p p r e s e n t a t o d a u n a t u p l a c o n t e n e n t e il n o m e , il c o g n o m e , l ' e t à e c c . ) . In u n o s c h e m a , o g n i e n t i t à h a u n n o m e c h e la i d e n t i f i c a u n i v o c a m e n t e e v i e n e r a p p r e s e n t a t a g r a f i c a m e n t e m e d i a n t e u n r e t t a n g o l o c o n il n o m e d e l l ' e n t i t à a l l ' i n t e r n o . L a F i g u r a 7 . 5 riporta a l c u n i e s e m p i di e n t i t à .

Relazioni (o associazioni)2 R a p p r e s e n t a n o legami logici, significativi per l ' a p p l i c a z i o n e di i n t e r e s s e , tra d u e o p i ù e n t i t à . R E S I D E N Z A è u n e s e m p i o di r e l a z i o n e c h e p u ò s u s s i s t e r e t r a le e n t i t à C I T T À e I M P I E G A T O m e n t r e E S A M E è u n

e s e m p i o di r e l a z i o n e c h e p u ò s u s s i s t e r e tra le e n t i t à S T U D E N T E e C O R S O . U n a

' In genere si utilizza il termine istanza invece di occorrenza, ma noi qui preferiamo occorrenza per non generare confusione con il concetto di istanza (insieme di tuple) utilizzato nel modello relazionale. "In questo capitolo verrà usato prevalentemente il termine relazione. Negli altri capitoli si userà invece il termine associazione in casi di possibile ambiguità (per esempio con le relazioni del modello relazionale).

Costrutti

Rappresentazione grafica

Entità

Relazione

Attributo semplice

-o

Attributo composto

Cardinalità di relazione (m,M)

Cardinalità di attributo

-o

Identificatore interno

Identificatore esterno

Generalizzazione

Sottoinsieme

Jftl

1

Figura 7.4 I c o s t r u t t i del m o d e l l o E-R e la l o r o r a p p r e s e n t a z i o n e g r a f i c a

o c c o r r e n z a di relazione è u n ' e n n u p l a (coppia nel c a s o più f r e q u e n t e di relazione binaria) costituita da o c c o r r e n z e di entità, una per ciascuna delle entità coinvolte. La c o p p i a di oggetti c o m p o s t a d a l l ' i m p i e g a t o Ferrari e dalla città di B o l o g n a , o p p u r e la c o p p i a di oggetti c o m p o s t a d a l l ' i m p i e g a t o Marini e dalla città di Firenze, s o n o e s e m p i di o c c o r r e n z e della relazione R E S I D E N Z A . E s e m p i di o c c o r r e n z e della relazione E S A M E tra le entità S T U D E N T E e C O R S O s o n o le coppie e\, e2,

DIPARTIMENTO

CITTÀ VENDITA

Figura 7.5 Esempi di entità nel modello E-R

€3, £4, e d