A. Veneziani - Soluzione (parte di Informatica) della simulazione
←
→
Trascrizione del contenuto della pagina
Se il tuo browser non visualizza correttamente la pagina, ti preghiamo di leggere il contenuto della pagina quaggiù
A. Veneziani – Soluzione (parte di Informatica) della simulazione di seconda prova Aprile 2019 Analisi del problema La traccia si suddivide in problematiche relative a sistemi ed altre relative ad informatica, coinvolgendo quest’anno tutt’e due le materie. Il testo: http://www.veneziani.altervista.org/ITIS_Luino_2018- 2019/Informatica/5A/dispense/DB/simulazione_2019_apr/Testo_Simulazione%20di%20seconda%20prova_2_Aprile_2019.pdf prospetta problematiche relative alla gestione di alcuni aspetti di una compagnia ferroviaria passeggeri, presumibilmente di linee ad alta velocità. I punti chiave messi in evidenza dal testo relativi alla materia di Informatica (di alcuni dei quali comunque non è richiesto lo sviluppo) sono: a) Registrazione di un utente sul sistema Web della compagnia EasyTrain b) Possibilità di effettuare prenotazioni, quindi selezione del giorno del viaggio, della tratta, della carrozza e del posto (semprechè liberi). c) Effettuare il pagamento relativo al punto (b) d) Permettere ai viaggiatori di scegliere in un catalogo di film, riportandone i dati salienti e) Registrare quali di essi sono stati visti da chi e in quale occasione In realtà in sostanza la traccia richiede esplicitamente di esaudire solo le richieste al punto (d) ed (e) della precedente lista. Per completezza il DB proposto come soluzione tiene conto anche degli aspetti relativi alla registrazione e al relativo accesso alla piattaforma di acquisto viaggi, e registra tutte le prenotazioni effettuate dei viaggi stessi. Punto 2 della traccia Costruzione del diagramma E/R del DB Per prima cosa consideriamo che il testo parla, come ovvio, di un accesso al sito di prenotazione, che comporta una identificazione dell’utente. Ciò ovviamente perchè sia il biglietto che la stessa operazione di prenotazione è personale. Questo è direttamente in relazione con le operazioni di registrazione e successivo accesso con identificazione. Prevederemo quindi una entità Utenti che raggruppi i dati delle persone che si registrano al sito di EasyTrain, con alcune informazioni utili, quali la loro mail ed ovviamente login e password. Tali utenti secondo quanto detto dal testo effettueranno delle prenotazioni relative a dei viaggi. Prevederemo quindi una entità Viaggi, che raggruppi le varie tratte tra le quali un utente possa scegliere ed effettuare quindi la prenotazione voluta. Ad ogni tratta sarà associato un prezzo specifico, eventualmente modificabile a seconda dei periodi e del rapporto domanda / offerta di posti. Sarà prevista anche una entità che registri quali utenti hanno effettuato quale viaggio (tratta), che chiameremo Prenotazioni. La registrazione del dato tratta / utente, assieme ad altri necessari, quali la data della prenotazione, il posto (carrozza + n° posto) prenotato sul treno ecc. prevede già il pagamento anticipato del costo del biglietto. In realtà quindi si suppone che Prenotazioni sia una entità che registri le prenotazioni degli Utenti e come tale sia in relazione 1 a n con essa (n lato Prenotazioni), in quanto un utente potrà effettuare più prenotazioni, ed una prenotazione riguarda ed è effettuata da un solo utente. Nello stesso modo Prenotazioni è correlata logicamente e quindi in associazione con Viaggi, in quanto una prenotazione riguarda inevitabilmente un viaggio (tratta). Mentre un viaggio può essere oggetto di molte prenotazioni. Quindi esiste una associazione tra Prenotazioni e Viaggi, con molteplicità 1 -> N da Viaggi verso Prenotazioni. A questa parte del diagramma, riguardante l’accesso e le prenotazioni, potremo combinare la parte relativa alla fruizione dei films durante il viaggio, oggetto di buona parte delle richieste della traccia. I films saranno catalogati grazie ad una apposita entità Films. Prevederemo un apposito attributo (In_Catalogo) per indicare se il film fa parte attualmente del catalogo corrente dei film proposti oppure no. Pagina 1
In caso negativo (valore 0), esso comunque indica che il film è stato in un qualche altro periodo in catalogo. La presenza di questo flag permette di evitare di dover cancellare dal DB tutti i film non in catalogo, permettendo quindi di mantenere i dati raccolti (n° visioni, ecc.) riguardo ad essi. Ovviamente prevederemo per questa entità tutti gli attributi indicati dalla traccia. La traccia mette in evidenza in particolare due dati la cui gestione pone delle particolarità. Films è in associazione con Prenotazioni, in quanto per visionare effettivamente qualcuno dei films, bisogna aver acquistato un biglietto e quindi aver effettuato una prenotazione, oltre ad essere effettivamente in viaggio. In questo caso si può dire che ad ogni prenotazione (con presenza), corrisponde la possibile visione di più films, e viceversa ad ogni film considerato corrisponde la visione da parte di più persone che hanno effettuato più prenotazioni. Si tratta quindi di una associazione N a M tra le due entità indicate. In linea di massima l’associazione da prenotazioni a films è parziale, perché non è detto che solo per aver prenotato e viaggiato l’utente veda per forza dei films, mentre l’associazione considerata dall’altro verso si può considerare totale, ipotizzando che nessun film abbia totalizzato in assoluto 0 visualizzazioni. Dovendo memorizzare i vari attori che hanno lavorato in un film è ovvio che non è opportuno semplicemente prevedere n attributi dello stesso tipo. Anche qui l’associazione Films Attori, è totale in entrambi i sensi, in quanto un film deve pur avere qualche attore che vi recita, e si può ipotizzare che un attore sia tale perche’ ha partecipato ad almeno un film. Si conformerà quindi una entità ulteriore Attori in associazione con Films con molteplicità N a M con essa. Questo in quanto: in un film potremo avere più attori che lo interpretano, ma viceversa anche un attore potrà senza dubbio interpretare più film. Tutto questo porta a concludere quanto già detto sopra riguardo all’associazione tra queste due entità e alla sua molteplicità. Per quanto riguarda l’attributo genere del film, può essere vantaggioso scorporare tale attributo facendolo divenire una entità autonoma, di modo da catalogare i vari generi in essa e fare quindi riferimento ad ognuno di essi quando necessario, dall’entità Films. In sintesi, come al solito, una operazione di questo tipo porta a una relazione 1 a N, in questo specifico caso tra l’entità Films (N) e l’entità Generi (1), in quanto dopo questa modifica del diagramma, ad un film corrisponde un solo genere, mentre ad un genere possono corrispondere più films. Anche questa associazione può ragionevolmente essere pensata come totale in tutte e due i sensi, in quanto ad un genere apparterrà almeno qualche film (anche per accontentare nel modo più ampio la clientela), e nel contempo ad un film non può non appartenere ad un genere. Entità e relativi attibuti Possiamo quindi alla fine di questa analisi fare un riepilogo delle entità e degli attributi considerati o di quello che vanno comunque aggiunti allo schema descritto prima: Entità Utenti CF codice fiscale dell’utente – chiave primaria Nome nome dell’utente Cognome cognome dell’utente Mail mail dell’utente Login username dell’utente (potrebbe essere generato automaticamente) Passwd password di accesso da abbinare al Login Entità Prenotazioni PU codice unico prenotazione – chiave primaria Carrozza numero della carrozza del treno Posto numero del posto nella carrozza indicata DataPreno data in cui avviene la prenotazione DataViaggio data di effettivo svolgimento del viaggio PrezzoBigl prezzo a cui è stato pagato il biglietto Presente indicatore booleano che indica se il passeggero era presente Pagina 2
Entità Viaggi Cod_Viaggio codice univoco relativo al viaggio – chiave primaria LuogoPart Luogo di partenza del viaggio LuogoArr Luogo di arrivo del viaggio PrezzoAtt prezzo a cui attualmente viene venduta la tratta Entità Films Cod_Film codice univoco relativo al singolo film – chiave primaria Titolo titolo del film Durata durata del film Anno anno in cui è stato prodotto il film Trama testo descrittivo della trama del film In_Catalogo indica se il film è attualmente in catalogo (cioè tra quelli visionabili) Entità Generi Cod_Genere codice univoco relativo ad un genere – chiave primaria Genere descrizione del genere Entità Attori Cod_Attore codice univoco relativo ad un attore – chiave primaria Nome nome dell’attore Cognome cognome dell’attore Relazioni - Modello logico Le entità ed il diagramma E/R ipotizzate sopra portano al seguente modello logico schematizzato dalle seguenti relazioni: Utenti(CF, Nome, Cognome, Mail, Login, Passwd) Viaggi(Cod_Viaggio, LuogoPart, LuogoArr, PrezzoAtt) Prenotazioni(PU, Carrozza, Posto, DataPreno, DataViaggio, PrezzoBigl, Presente, CF, Cod_Viaggio) Films(Cod_Film, Titolo, Durata, Anno, Trama, In_Catalogo, Cod_Genere) Visioni(PU, Cod_Film) Attori(Cod_Attore, Nome, Cognome) Attori_Films(Cod_Films, Cod_Attore) Generi(Cod_Genere, Genere) Forma tabellare delle relazioni Relazione Utenti Nome campo Tipo Ampiezza NULL Chiavi CF CHAR(16) 16 No Primaria Nome VARCHAR(40) 40 No Cognome VARCHAR(40) 40 No Mail VARCHAR(70) 70 No Login VARCHAR(20) 20 No Passwd VARCHAR(20) 20 No Relazione Viaggi Nome campo Tipo Ampiezza NULL Chiavi Cod_Viaggio INT UNSIGNED No Primaria Pagina 3
LuogoPart VARCHAR(30) 30 No LuogoArr VARCHAR(30) 30 No PrezzoAtt DECIMAL(5,2) 5 No Relazione Prenotazioni Nome campo Tipo Ampiezza NULL Chiavi Cod_Film INT UNSIGNED No Primaria Carrozza TINYINT No Posto TINYINT No DataPreno DATE No DataViaggio DATE No PrezzoBigl DECIMAL(5,2) 5 No Presente BIT(1) Si CF CHARF(16) 16 No Esterna Cod_Viaggio INT UNSIGNED No Esterna Relazione Films Nome campo Tipo Ampiezza NULL Chiavi PU INT UNSIGNED No Primaria Titolo VARCHAR(100) 100 No Durata TIME No Anno YEAR No Trama TEXT No In_Catalogo BIT 1 No Cod_Genere INT UNSIGNED No Esterna Relazione Visioni Nome campo Tipo Ampiezza NULL Chiavi PU INT UNSIGNED No Primaria Cod_Film INT UNSIGNED No Relazione Attori Nome campo Tipo Ampiezza NULL Chiavi Cod_Attore INT UNSIGNED No Primaria Nome VARCHAR(40) 40 No Cognome VARCHAR(40) 40 No Relazione Attori_Films Nome campo Tipo Ampiezza NULL Chiavi Cod_Attore INT UNSIGNED No Primaria Cod_Film INT UNSIGNED No Relazione Generi Nome campo Tipo Ampiezza NULL Chiavi Cod_Genere INT UNSIGNED No Primaria Genere VARCHAR(50) 50 No Pagina 4
Script SQL di generazione del DB Lo script che permette di generare il DB con la struttura precedentemente descritta, completo di vincoli di integrità referenziale, risulta. L’ordine della creazione delle tabelle è vincolato, per alcune di esse, dalla presenza dei vincoli di integrità referenziale: CREATE TABLE Attori ( Cod_Attore INT UNSIGNED PRIMARY KEY, Nome VARCHAR(40) NOT NULL, Cognome VARCHAR(40) NOT NULL ); CREATE TABLE Generi ( Cod_Genere INT UNSIGNED PRIMARY KEY, Genere VARCHAR(50) NOT NULL ); CREATE TABLE Utenti ( CF CHAR(16) PRIMARY KEY, Nome VARCHAR(40) NOT NULL, Cognome VARCHAR(40) NOT NULL, Email VARCHAR(70) NOT NULL, CartaCredito CHAR(16) NOT NULL, TipoCarta ENUM('Visa', 'MasterCard', 'American Express', 'Postepay') NOT NULL, Login VARCHAR(20) NOT NULL, Passwd VARCHAR(20) NOT NULL ); CREATE TABLE Viaggi ( Cod_Viaggio INT UNSIGNED PRIMARY KEY, LuogoPart VARCHAR(30) NOT NULL, LuogoArr VARCHAR(30) NOT NULL, PrezzoAtt DECIMAL(5,2) ); CREATE TABLE Films ( Cod_Film INT UNSIGNED PRIMARY KEY, Titolo VARCHAR(100) NOT NULL, Durata TIME NOT NULL, Anno YEAR NOT NULL, Trama TEXT NOT NULL, In_Catalogo BIT NOT NULL, Cod_Genere INT UNSIGNED NOT NULL, FOREIGN KEY(Cod_Genere) REFERENCES Generi(Cod_Genere) ); CREATE TABLE Attori_Films ( Cod_Attore INT UNSIGNED NOT NULL, Cod_Film INT UNSIGNED NOT NULL, PRIMARY KEY(Cod_Attore, Cod_Film), FOREIGN KEY(Cod_Attore) REFERENCES Attori(Cod_Attore), FOREIGN KEY(Cod_Film) REFERENCES Films(Cod_Film) ); CREATE TABLE Prenotazioni ( PU INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, Carrozza TINYINT NOT NULL, Pagina 5
Posto TINYINT NOT NULL, DataPreno DATE NOT NULL, DataViaggio DATE NOT NULL, PrezzoBigl DECIMAL(5,2) NOT NULL, Presente BIT, CF CHAR(16) NOT NULL, Cod_Viaggio I NT UNSIGNED NOT NULL, FOREIGN KEY(CF) REFERENCES Utenti(CF), FOREIGN KEY(Cod_Viaggio) REFERENCES Viaggi(Cod_Viaggio) ); CREATE TABLE Visioni ( PU INT UNSIGNED NOT NULL, Cod_Film INT UNSIGNED NOT NULL, PRIMARY KEY(PU, Cod_Film), FOREIGN KEY(PU) REFERENCES Prenotazioni(PU), FOREIGN KEY(Cod_Film) REFERENCES Films(Cod_Film) ); Diagramma UML del DB Pagina 6
Punto 3 della traccia – svolgimento query Svolgiamo qui le query richieste in questo punto sul DB appena creato. Query a) Elenco dei film in catalogo ordinati per genere ed anno di produzione # # elenco dei films in catalogo ordinati per genere e anno di produzione # SELECT Titolo, genere, anno FROM films, generi WHERE films.Cod_Genere = generi.Cod_Genere AND films.In_Catalogo = 1 ORDER BY genere, anno; si tratta di effettuare un join tra le tabelle films e generi (per poter accedere anche alle denominazioni dei generi, ovviamente in relazione ad ogni film considerato). Su tale join si effettua un ordinamento su un doppio criterio (genere ed anno). Dall’elenco sono esclusi, come richiesto dal testo i film ormai non più in catalogo, ossia quelli che non sono nella lista dei visionabili (catalogo corrente). Query b) Elenco in ordine alfabetico degli utenti che non hanno mai visualizzato alcun film Per risolvere il problema posto si può iniziare a considerare una query che estragga gli utenti che hanno visualizzato films (in particolare il dato che gli identifica univocamente e senza ambiguità, ossia in questo caso la loro chiave primaria codice fiscale). # codice fiscale di utenti che hanno visualizzato films SELECT utenti.CF FROM utenti, prenotazioni, visioni, films WHERE utenti.CF = prenotazioni.CF AND prenotazioni.PU = visioni.PU AND visioni.Cod_Film = films.Cod_Film; Tale query produce quindi un insieme di codici fiscali, probabilmente sottinsieme di tutti i codici fiscali presenti in utenti. Per trovare gli utenti che non hanno visualizzato alcun film, basta poi effettuare una query su utenti che abbia come condizione quella di avere la chiave primaria non presente come risultato della query indicata sopra (qui facente la funzione di una subquery) # # elenco in ordine alfabetico degli utenti che non hanno mai visualizzato alcun film # SELECT Cognome, Nome FROM utenti WHERE CF NOT IN (SELECT utenti.CF FROM utenti, prenotazioni, visioni, films WHERE utenti.CF = prenotazioni.CF AND prenotazioni.PU = visioni.PU AND visioni.Cod_Film = films.Cod_Film) Pagina 7
ORDER BY Cognome; Infine si deve aggiungere un ordinamento per cognome al tutto, in quanto richiesto dal testo del punto (b) Si tratta in definitiva di una operazione di sottrazione sullo stesso insieme di un suo sottinsieme. L’insieme di tutti gli utenti – l’insieme degli utenti che hanno visto film = insieme degli utenti che non hanno visto alcun film. Query c) Dato un intervallo di tempo tra due date, produrre il titolo che ha registrato il maggior numero di visualizzazioni. Considero e creo la view che calcola quante volte è stato visto ognuno dei film, nel periodo prefissato # # Appoggiandosi ad una View # CREATE OR REPLACE VIEW ContaVisioni AS SELECT Titolo, COUNT(*) AS 'NumeroVisioni' FROM prenotazioni, visioni, films WHERE prenotazioni.PU = visioni.PU AND visioni.Cod_Film = films.Cod_Film AND DataViaggio > '2019-03-01' AND DataViaggio < '2019-03-15' GROUP BY films.Cod_Film; La subquery1: (SELECT MAX(NumeroVisioni) FROM ContaVisioni); utilizzante la view appena definita, calcola il numero massimo di tali visualizzazioni (per uno o piu’ film, quelli più visti). Una view in sostanza si comporta come una nuova tabella in realtà generata però da operazioni di selezione su quelle già preesistenti nel DB. Deduco infine, con la query sottostante, quale è il film più visto (in quanto dalla tabella che elenca il numero di visualizzazioni per ogni film, scelgo solo quelli con il numero di visualizzazioni che risulta il massimo, ovviamente sempre nel periodo di interesse): # # e quindi la query # "dato un intervallo di tempo produrre il titolo che ha registrato # il maggior numero di visualizzazioni" # diviene: SELECT Titolo, NumeroVisioni FROM ContaVisioni WHERE NumeroVisioni = (SELECT MAX(NumeroVisioni) FROM ContaVisioni); 1 Una subquery è una query, inserita a sua volta in una query di livello superiore, atta a permettere a quest’ultima di ottenere i risultati voluti. Pagina 8
ovviamente con l’uso della view considerata Altrimenti potrei procedere in questo modo: Inizio a ricavare il numero di visioni di un certo film in un certo periodo di tempo (analogamente alla query fatta sopra, inserita nella view). Per realizzare questa query ho bisogno di Films, perché considero i film e ho bisogno del loro titolo, della tabella Visioni, perché indica le visioni dei film stessi ed infine della tabella Prenotazioni perché in tale entità c’è la data effettiva di esecuzione del viaggio, nella quale, eventualmente, saranno visionati i film: # numero di visioni per ogni film in un certo periodo SELECT Titolo, COUNT(*) NumeroVisioni FROM prenotazioni, visioni, films WHERE prenotazioni.PU = visioni.PU AND visioni.Cod_Film = films.Cod_Film AND prenotazioni.DataViaggio > '2019-03-01' AND prenotazioni.DataViaggio < '2019-03-15' GROUP BY films.Cod_Film; per effettuare questo conteggio per ogni film, devo raggruppare per film. A questo punto si pone comunque il problema di trovare il massimo nella tabella appena considerata. E’ possibile, a tal proposito, in SQL, utilizzare i risultati di una query come se fossero a loro volta una tabella, anche in modo diretto (non solo generando una view come prima). Utilizzando quindi la query precedente come una tabella, ossia inserendo la stessa come subquery nella parte FROM di un comando SELECT di livello più alto che utilizzi questa query appunto per individuare il valore massimo di visualizzazioni, dato il report di numero di visualizzazioni che la stessa contiene: # massimo numero (assoluto) di visualizzazioni di un film SELECT MAX(NumeroVisioni) FROM (SELECT COUNT(*) NumeroVisioni FROM prenotazioni, visioni, films WHERE prenotazioni.PU = visioni.PU AND visioni.Cod_Film = films.Cod_Film AND prenotazioni.DataViaggio > '2019-03-01' AND prenotazioni.DataViaggio < '2019-03-15' GROUP BY films.Cod_Film) AS T1; Si noti che alla subquery si è dovuto per forza dare un alias (ossia un nome). In tal caso si parla di alias di tabella, ossia è stato necessario dare un nome alla tabella appena utilizzata (che non può rimanere anonima). Determinato il massimo di visualizzazioni in questo modo è possibile utilizzare una variante della clausola GROUP BY per determinare quali conteggi su ogni film siano pari al valore massimo: In pratica posso immaginare di riscrivere la query che effettua i conteggi delle visualizzazioni per ognuno dei film: # titolo di film che ha registrato il massimo numero di visualizzazioni # in un certo intervallo di tempo SELECT Titolo, COUNT(*) FROM prenotazioni, visioni, films WHERE prenotazioni.PU = visioni.PU AND Pagina 9
visioni.Cod_Film = films.Cod_Film AND prenotazioni.DataViaggio > '2019-03-01' AND prenotazioni.DataViaggio < '2019-03-15' GROUP BY films.Cod_Film HAVING COUNT(*) = (SELECT MAX(NumeroVisioni) FROM (SELECT COUNT(*) NumeroVisioni FROM prenotazioni, visioni, films WHERE prenotazioni.PU = visioni.PU AND visioni.Cod_Film = films.Cod_Film AND prenotazioni.DataViaggio > '2019-03-01' AND prenotazioni.DataViaggio < '2019-03-15' GROUP BY films.Cod_Film) AS T1); La clausola HAVING permette di aggiungere una condizione sui risultati calcolati dalla funzione di aggregazione. In questo caso abbiamo richiesto che il conteggio delle visualizzazioni dei films, accaduto in un certo lasso di tempo, sia pari al massimo precedentemente determinato con la subquery considerata prima. Parte IIa Punto I Per realizzare la pagina si è scelto di implementare il problema della query (b). In questo caso la realizzazione è immediata; una volta scritta la query basta inserirla in una pagina avente il codice PHP necessario per interfacciare i risultati a PHP stesso, in questo modo: Implementazione pagina punto I seconda parte Utenti che non hanno visualizzato alcun film (nei vari viaggi):
$riga = mysqli_fetch_array($rs); while ($riga) { echo $riga['Cognome'] . " " . $riga['Nome'] . ""; $riga = mysqli_fetch_array($rs); } ?> Punto III Il punto richiede di effettuare alcune operazioni sullo schema di relazioni: FARMACO (COD_F,NOME_F,DATA_PREPARAZIONE,DATA_SCADENZA,PREZZO) COMPONENTE (COD_C,NOME_C,DESCRIZIONE) CONTIENE (ID_FARMACO,ID_COMPONENTE,QUANTITA_C) a) disegnare il diagramma del modello concettuale corrispondente; Il diagramma E/R relativo alle relazioni indicate risulta il seguente2: N M Farmaco contiene Componente b) definire in linguaggio SQL il modello fisico corrispondente tenendo conto dei vincoli di integrità referenziali e/o vincoli di dominio; CREATE TABLE Farmaco ( COD_F INT UNSIGNED PRIMARY KEY, NOME_F VARCHAR(40) NOT NULL, DATA_PREPARAZIONE DATE NOT NULL, DATA_SCADENZA DATE NOT NULL, PREZZO DECIMAL(5,2), CHECK(DATA_PREPARAZIONE < DATA_SCADENZA) ); CREATE TABLE Componente ( COD_C INT UNSIGNED PRIMARY KEY, NOME_C VARCHAR(40) NOT NULL, DESCRIZIONE TEXT NOT NULL); CREATE TABLE Contiene ( COD_F INT UNSIGNED NOT NULL, COD_C INT UNSIGNED NOT NULL, 2 Non si indicano qui gli attributi perché l’operazione risulta graficamente lunga da svolgere Pagina 11
PRIMARY KEY(COD_F, COD_C), QUANTITA_C SMALLINT UNSIGNED NOT NULL, FOREIGN KEY(COD_F) REFERENCES Farmaco(COD_F) ); FOREIGN KEY(COD_C) REFERENCES Componente(COD_C) ); c) esporre il significato delle varie tipologie di vincoli che si possono riscontrare nella progettazione delle basi di dati e dei riflessi che essi hanno sulle operazioni di inserimento, aggiornamento e cancellazione. Nella realizzazione della precedente base di dati elementare abbiamo utilizzato vincoli di tre tipologie: vincoli di chiave primaria vincoli di integrità vincoli di integrità referenziale Nello schema per quanto riguarda i vincoli di chiave primaria abbiamo due campi chiave primaria semplici (COD_F e COD_C) ed un campo chiave primaria composito (COD_F e COD_C) su Contiene. Nel campo chiave primaria composito il DBMS controlla che non ci siano delle ripetizioni delle coppie di valori (COD_F, COD_C)3. Un vincolo di integrità è stato utilizzato per garantire che non ci siano sovrapposizioni di data tra la data di preparazione e quella di scadenza del farmaco. Sicuramente infatti per quanto riguarda queste date deve essere DataPreparazione < DataScadenza. Questo è imposto tramite l’istruzione CHECK(….)4. Per quanto riguarda i vincoli di integrità referenziale, essi effettuano dei controlli tra i valori delle chiavi primarie e chiavi esterne, coinvolte nelle associazioni. In questo caso la coppia di chiavi primarie ed esterne coinvolta data la relazione n a m “contiene” è: 1) COD_F su Farmaco (Primaria) COD_F su Contiene (Esterna) 2) COD_C su Componente (Primaria) COD_C su Contiene (Esterna) I valori di questi due vincoli non devono mai presentare incoerenze, se sono stati posti come controllo dei vincoli di integrità referenziali. Ad esempio: In Contiene non posso avere l’indicazione di un farmaco che non sia presente anche in Farmaco. Un riferimento di un codice di farmaco deve sempre avere corrispondenza nella tabella Farmaco. Idem per la tabella Componente. In Contiene non è possibile avere riferimenti a componenti il cui codice non esiste nella tabella Componenti. E’ possibile viceversa sempre avere codici di Farmaci e Componenti che non abbiano riferimenti in Contiene. Non è possibile cancellare Farmaci che abbiano associate delle tuple in Contiene5 Non è possibile cancellare Componenti che abbiano delle tuple associate in Contiene Non è possibile modificare il codice di un farmaco che abbia associazioni in Contiene Non è possibile modificare il codice di un componente che abbia associazioni in Contiene Non è possibile inserire in Contiene elementi che associno farmaci o componenti che non esistono 3 In quanto non ha senso che un componente sia citato più volte nella formulazione di un medicinale. 4 Si ricorda che l’istruzione CHECK è stata implementata ed è quindi disponibile solo nelle ultimissime versioni di MySQL e MariaDB. Nelle precedenti versioni essa non ha effetto pratico. 5 Questo con la sintassi ed il tipo di vincolo indicato; ulteriori cossiderazioni possono essere fatte nel caso di presenza delle clausole ON UPDATE…. ed ON DELETE…. Pagina 12
Puoi anche leggere