Lezione 8 Metadati, Viste e Trigger Pag.1
Metadati e catalogo di sistema I metadati sono dati a proposito dei dati (quali tabelle esistono?, quali campi contengono?, quante tuple contengono?, ci sono vincoli (chiavi, chiavi esterne, costraint)?, esistono viste, trigger, procedure?) I metadati sono ordinariamente ricavabili in SQL con comandi del tipo show (describe nel dialetto di Oracle). Ad esempio: show tables elenca le tabelle di un database show create table descrive una tabella in termini di comando utilizzato per la sua creazione Rif.: http://www.quest-pipelines.com/newsletter-v6/0905_a.htm Pag.2
Metadati e catalogo di sistema Le informazioni relative ai metadati di un database sono strutturate: posso rappresentarle in un database! SQL standard (ISO/IEC 9075) prevede che i metadati di un DBMS siano organizzati in un database denominato information_schema Mysql dalla versione 5.0.2 implementa una versione base dell information_schema Rif.: http://www.quest-pipelines.com/newsletter-v6/0905_a.htm Pag.3
L information_schema: rappresentazione E-R Fonte: http://www.xcdsql.org/misc/mysql_information_schema.html Pag.4
L information_schema E un database quasi a tutti gli effetti E fatto di tabelle Posso eseguire query su queste tabelle Non posso alterare il contenuto delle tabelle o la loro struttura (concettualmente è di sola lettura) Il suo aggiornamento e eseguito dal sistema in automatico per ogni modifica dei DB gestiti dal DBMS Rif.: http://www.quest-pipelines.com/newsletter-v6/0905_a.htm Pag.5
Viste Una vista non è che una relazione, ma ne viene memorizzata la definizione, piuttosto che l insieme di tuple CREATE VIEW VelistiAttivi (vid, vnome, eta, bid, giorno) AS SELECT V.vid, V.vnome, V.eta, P.bid, P.giorno FROM Velisti V, Prenota P WHERE V.vid = P.vid AND V.eta > 6 Le viste possono essere cancellate usando il comando DROP VIEW Come gestire DROP TABLE se c è una vista su quella tabella o vincoli di chiave esterna? Aggiungo RESTRICT se voglio che non venga eseguita Aggiungo CASCADE se voglio distruggere anche tutte le viste e i vincoli di integrità collegati Pag.6
Viste e sicurezza Le viste possono essere usate per presentare le informazioni necessarie (o un loro riassunto), nascondendo al contempo i dettagli della/e relazione/i sottostante/i Data VelistiAttivi, ma non Velisti o Prenota, possiamo trovare i velisti che hanno una prenotazione, ma non i bid delle barche che sono state prenotate. I comandi GRANT/REVOKE possono essere usati per controllare l accesso alle relazioni e alle viste Insieme all abilità di definire le viste, questo fornisce un meccanismo di controllo di accesso molto potente Pag.7
Viste aggiornabili Le viste sono come relazioni di base sulle interrogazioni Non è vero per gli aggiornamenti! Aggiornamento di vista deve agire sulle relazioni sottostanti Qualcosa di ambiguo o addirittura impossibile! Vietato nello standard, a meno che (Viste aggiornabili - standard SQL-92): Viste definite su una singola tabella di base Costruite solo per selezione e proiezione (scelta di record, scelta di campi): sono quindi escluse le subquery Mysql consente di agire anche su join di tabelle (a condizione di agire solo su una tabella per volta) Pag.8
I trigger Una procedura che viene attivata al presentarsi di un cambiamento della base di dati (evento) L esecuzione di una azione è condizionata alla verifica di una condizione (interrogazione o test) Il trigger può essere eseguito prima dei cambiamenti che lo hanno attivato (prima della commit) ed eventualmente ripristinare la situazione precedente a tali cambiamenti Pag.9
I trigger (2) L azione può essere richiesta per ogni singola riga che ha scatenato l azione (for each row) E possibile riferirsi sia ai valori che le tuple avevano prima dell evento / hanno dopo l evento (rispettivamente hanno prima dell evento / avrebbero dopo l evento) Un trigger può sostituire completamente il comando attivante o essere eseguito in differita al termine della transazione Pag.10
I trigger (2) L azione può essere richiesta per ogni singola riga che ha scatenato l azione (for each row) E possibile riferirsi sia ai valori che le tuple avevano prima dell evento / hanno dopo l evento (rispettivamente hanno prima dell evento / avrebbero dopo l evento) Un trigger può sostituire completamente il comando attivante o essere eseguito in differita al termine della transazione Pag.11
Un trigger per i velisti esperti CREATE TRIGGER upd_exp AFTER Insert on prenota FOR EACH ROW BEGIN update velisti set esperienza = valutavelista(velisti.vid); END; Pag.12
Una funzione per calcolare l esperienza CREATE FUNCTION valutavelista (velistaid INTEGER) RETURNS INTEGER begin DECLARE esperienza INTEGER; DECLARE numris INTEGER; SET numris = (SELECT COUNT(*) FROM Prenota P WHERE P.vid = velistaid); IF (numris > 2) then set esperienza = numris - 2; ELSE set esperienza = 0; END IF; IF (esperienza > 10) then set esperienza = 10; End if; RETURN esperienza; end Pag.13
Trigger e viste: Un caso pratico in MySql 5 La Acme Inc. desidera gestire il proprio sistema di incassi in modo più sicuro che in passato Il vecchio sistema era basato su una singola tabella (incassi) di un DB (incassi) che consentiva di tracciare la data dell incasso, l importo, il nome del cliente che aveva effettuato il pagamento, il nome del cassiere che aveva effettuato l operazione Pag.14
La tabella originale Create database incassi; Connect incassi; Create table incassi(id_incasso integer primary key, cassiere varchar(16), importo real, cliente varchar(16), tempo timestamp); Osservazioni: Il cassiere aveva libertà di inserire il proprio nome (o uno di fantasia) Nessuna delle modifiche sul medesimo incasso (a causa dello schema utilizzato) potevano essere tracciate Notare l uso del tipo timestamp che per default traccia in automatico data e ora dell ultima modifica (implicitamente dice: NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP) Pag.15
Modifiche allo schema E opportuno non modificare lo schema per gestire lo storico o inseriamo una forzatura su un piano semantico La soluzione può essere creare una seconda tabella che gestisca lo storico delle modifiche Create table archivio_incassi(id_incasso integer, cassiere varchar(16), importo real, cliente varchar(16), tempo timestamp default 0, status char(1), checksum varchar(32), primary key(id_incasso,tempo)); Notare: la colonna status che consente di salvare, come vedremo, l azione di cancellazione(i = insert, U = update, D = delete), la chiave su id_incasso, tempo che non consente due azioni contemporanee sullo stesso incasso Il default a 0 su timestamp la inizializza vuota Checksum come vedremo innalza la sicurezza Pag.16
Utenti e viste Creiamo una vista che consente di inserire, modificare, cancellare incassi ma non di agire sull archivio o modificare dati su orari e utenti che hanno effettuato le modifiche Create view cassa (id_incasso, importo, cliente) as select id_incasso, importo, cliente from incassi; Creiamo due cassieri che avranno diritto di lavorare solo su cassa Grant SELECT, INSERT, UPDATE, DELETE on incassi.cassa to pippo @ localhost identified by pippo Grant SELECT, INSERT, UPDATE, DELETE on incassi.cassa to pluto @ localhost identified by pluto Dobbiamo aggiungere il diritto ad aggiungere righe nell archivio (ma non potranno togliere o vedere nulla) o il tutto non funzionera Grant INSERT on incassi.archivio_incassi to pippo @ localhost Grant INSERT on incassi.archivio_incassi to pluto @ localhost Pag.17
Trigger per tabella principale Rimane da automatizzare: 1) l aggiornamento della tabella principale (per il solo nome del cassiere, come visto timestamp gestisce i cambi di orario in automatico), Create trigger log1 before insert on incassi For each row begin Set New.cassiere = user(); End Create trigger log2 before update on incassi For each row begin Set New.cassiere = user(); End Pag.18
Trigger per tabella archivio 2) la gestione dell archivio (notare la rudimentale checksum che evita che l utente possa simulare inserimenti in tabella) Create trigger log3 after insert on incassi For each row begin Insert into archivio_incassi (id_incasso, cassiere, importo, cliente, tempo, status,checksum) values (new.id_incasso, new.cassiere, new.importo, new.cliente, new.tempo, I, new.id_incasso + 100 * new.importo); End Create trigger log4 after update on incassi For each row begin Insert into archivio_incassi (id_incasso, cassiere, importo, cliente, tempo, status, checksum) values (new.id_incasso, new.cassiere, new.importo, new.cliente, new.tempo, U,new.id_incasso + 100 * new.importo); End Create trigger log5 after delete on incassi For each row begin Insert into archivio_incassi (id_incasso, cassiere, importo, cliente, tempo, status, checksum) values (old.id_incasso, user(), old.importo, old.cliente, current_timestamp(), D, old.id_incasso + 100 * old.importo); End Pag.19