In generale, la gestione degli errori nei database è simile a quella degli altri errori del runtime. È opportuno scrivere il codice in modo che sia in grado di affrontare eventuali errori che si possono verificare e reagire ad essi invece che lasciare che sia il runtime a farlo. È possibile dividere gli errori dei database, a grandi linee, in tre categorie: gli errori di connessione, gli errori di sintassi SQL e gli errori relativi ai vincoli.
Errori di connessione
La maggior parte degli errori dei database riguardano la connessione e possono verificarsi nel corso di qualsiasi operazione. Anche se esistono strategie di prevenzione degli errori di connessione, solo raramente è possibile riprendersi in modo non traumatico da tale tipo di errori se il database rappresenta una parte vitale dell'applicazione.
La maggior parte degli errori di connessione riguarda il modo in cui il runtime interagisce con il sistema operativo, il file system e il file del database. Ad esempio, si verifica un errore di connessione nel caso in cui l'utente non sia autorizzato a creare un file di database in una particolare posizione nel file system. Le seguenti strategie possono contribuire ad evitare gli errori di connessione.
-
Utilizzate file di database specifici per ciascun utente
-
Invece che fare uso di un solo file di database per tutti gli utenti che utilizzano l'applicazione su un certo computer, fornite a ciascuno degli utenti un file di database. Il file si deve trovare in una directory associata all'account dell'utente. Ad esempio, può trovarsi nella directory di memorizzazione dell'applicazione o nella cartella dei documenti dell'utente o sul suo desktop, e così via.
-
Prendete in considerazione i diversi tipi di utente
-
Provate l'applicazione con tipi diversi di account utente e su diversi sistemi operativi e non partite dal presupposto che l'utente abbia le autorizzazioni di amministratore sul computer. Inoltre, non partite dal presupposto che la persona che ha installato l'applicazione sia necessariamente l'utente che la esegue.
-
Prendete in considerazione diverse posizioni dei file
-
Se consentite agli utenti di specificare il percorso di salvataggio di un file di database o di selezione di un file da aprire, considerate le varie posizioni dei file che gli utenti possono voler usare. Inoltre, prendete in considerazione la creazione di limiti alle posizioni in cui gli utenti possono memorizzare (o da cui possono aprire) i file di database. Ad esempio, si può consentire agli utenti di aprire solo i file contenuti nelle posizioni di memorizzazione nell'ambito del loro account.
Se si verifica un errore di connessione, è molto probabile che abbia luogo a seguito del primo tentativo di creazione o apertura del database. Di conseguenza l'utente non sarà in grado di eseguire nell'applicazione nessuna operazione concernente il database. Per alcuni tipi di errore, come quelli di sola lettura o relativi alle autorizzazioni, una possibile tecnica di ripristino è la creazione di una copia del file del database in una posizione diversa. L'applicazione può copiare il file del database in una posizione diversa, in cui l'utente ha l'autorizzazione a creare e modificare i file, ed utilizzare tale posizione.
Errori di sintassi
Si verifica un errore di sintassi nei casi in cui l'istruzione SQL sia stata composta in modo errato e l'applicazione tenti di eseguirla. Poiché le istruzioni SQL dei database locali vengono create come stringhe, non è possibile il controllo della sintassi SQL al momento della compilazione. Per poterne controllare la sintassi, tutte le istruzioni SQL devono essere eseguite. Utilizzate le seguenti strategie per evitare gli errori di sintassi.
-
Provate con cura tutte le istruzioni SQL
-
Se possibile, nel corso dello sviluppo dell'applicazione, provate le istruzioni SQL separatamente prima di inserirle come testo delle istruzioni nel codice dell'applicazione stessa. Seguite inoltre un metodo di prova del codice come l'unit testing per creare un set di prove che eseguano tutte le possibili opzioni e variazioni del codice.
-
Utilizzate i parametri nelle istruzioni ed evitate di concatenare (cioè generare in modo dinamico) l'SQL
-
Se si fa uso dei parametri e si evita l'uso di istruzioni SQL costruiti in modo dinamico, tutte le volte che un'istruzione SQL viene eseguita verrà utilizzato lo stesso testo che la compone. Di conseguenza sarà molto più facile provare le istruzioni e ridurre il numero delle possibili variazioni. Se è inevitabile generare un'istruzione SQL in modo dinamico, è opportuno ridurne al minimo le parti dinamiche. Controllate inoltre la validità degli eventuali interventi dell'utente per assicurare che non provochino errori di sintassi.
Per riprendersi da un errore di sintassi, l'applicazione necessita di una logica complessa che le consenta di esaminare le istruzioni SQL e correggerne la sintassi. Se vi attenete alle istruzioni generali di cui sopra per la prevenzione degli errori di sintassi, il codice sarà in grado di identificare le potenziali fonti di errori di sintassi SQL nel runtime, come ad esempio l'uso dell'intervento dell'utente in un'istruzione. Per il recupero da un errore di sintassi, date istruzioni all'utente indicandogli che cosa correggere per far sì che l'istruzione venga eseguita in modo appropriato.
Errori relativi ai vincoli
Gli errori di vincolo si verificano quando l'istruzione
INSERT
o
UPDATE
cerca di aggiungere dati a una colonna. L'errore ha luogo nei casi in cui i nuovi dati infrangano uno dei vincoli definiti relativamente alla tabella o alla colonna. Il set di possibili vincoli comprende i seguenti.
-
Vincolo di univocità
-
Indica che in tutte le righe di una tabella non possono essere presenti valori duplicati in una colonna. In alternativa, quando più colonne sono raggruppate sotto un vincolo di univocità, la combinazione dei valori di tali colonne non deve essere duplicata. Ciò vale a dire che, nell'ambito della colonna o delle colonne univoche specificate, ciascuna riga deve essere diversa dalle altre.
-
Vincolo della chiave primaria
-
Dal punto di vista dei dati consentiti o meno da un certo vincolo, il vincolo della chiave primaria è identico al vincolo di univocità.
-
Vincolo valore non Null
-
Stabilisce che una singola colonna non consenta la memorizzazione di un valore
NULL
e che, di conseguenza, in tutte le righe tale colonna debba avere un valore.
-
Vincolo di controllo
-
Consente di specificare un vincolo arbitrario su una o più tabelle. Un vincolo di controllo comune è la regola che stabilisce che il valore di una colonna debba rientrare in certi limiti, ad esempio che il valore di una colonna numerica sia maggiore di zero. Un altro tipo comune di tale vincolo specifica le relazioni che devono sussistere fra i valori delle colonne, ad esempio stabilendo che il valore di una certa colonna debba essere diverso da quello di un'altra colonna facente parte della stessa riga.
-
Vincolo del tipo di dati (affinità fra colonne)
-
Il runtime stabilisce quali tipi di dati sono consentiti nei valori delle colonne e dà luogo a un errore se si tenta di memorizzare in una colonna un valore del tipo errato. Tuttavia, in molte situazioni i valori vengono convertiti in modo da adeguarsi al tipo di dati dichiarato per la colonna a cui sono destinati. Per ulteriori informazioni, consultate
Utilizzo dei tipi di dati nei database
.
Il runtime non applica vincoli ai valori della chiave esterna; ciò significa che non è necessario che tali valori corrispondano al valore della chiave primaria già esistente.
Oltre ai tipi di vincolo predefiniti, il motore SQL del runtime supporta l'utilizzo dei trigger, che sono simili ai gestori di eventi. Si tratta di un set predefinito di istruzioni che vengono eseguite quando ha luogo una certa azione. Ad esempio, si può definire un trigger da eseguire quando vengono inseriti o eliminati dati in una particolare tabella. Un possibile utilizzo del trigger è per l'esame delle modifiche apportate ai dati e per la creazione di un errore nel caso in cui non vengano rispettate certe condizioni. Di conseguenza, il trigger può avere lo stesso scopo del vincolo e le strategie di prevenzione e recupero dagli errori relativi ai vincoli sono valide anche nel caso degli errori generati dai trigger. L'ID degli errori generati dai trigger è comunque diverso dall'ID degli errori di vincolo.
Il set di vincoli che si applica ad una certa tabella si determina al momento della progettazione dell'applicazione. L'aggiunta degli appositi vincoli facilita la progettazione dell'applicazione in modo da renderla in grado di prevenire gli errori di vincolo e riprendersi da essi. La previsione e la prevenzione sistematiche degli errori di vincolo sono tuttavia difficoltose. La previsione è infatti ostacolata dal fatto che gli errori relativi ai vincoli non si presentano finché non si aggiungono dati all'applicazione: tali errori si presentano con i dati che vengono aggiunti al database dopo che è stato creato e sono spesso il risultato del rapporto fra i nuovi dati e quelli già presenti nel database. Le seguenti strategie possono contribuire ad evitare molti errori dei vincoli.
-
Progettate con cura la struttura del database e i vincoli
-
Lo scopo dei vincoli è di far rispettare le regole dell'applicazione e contribuire a proteggere l'integrità dei dati del database. Quando progettate l'applicazione, cercate di strutturare il database in modo che sostenga l'applicazione. Come parte di tale procedimento, identificate le regole che si applicano ai dati; decidete ad esempio se certi valori sono obbligatori, se un certo valore deve essere predefinito, se è consentita la presenza di valori duplicati, e così via. Tali regole serviranno da guida nella creazione dei vincoli del database.
-
Specificate i nomi delle colonne in modo esplicito
-
È possibile scrivere l'istruzione
INSERT
senza specificare esplicitamente le colonne nelle quali devono essere inseriti i valori; tuttavia, così facendo si corre un rischio inutile. Denominando in modo esplicito le colonne in cui inserire i valori è possibile consentire la presenza dei valori generati automaticamente, delle colonne contenenti valori predefiniti e delle colonne che accettano i valori
NULL
. Inoltre, così facendo si può essere sicuri che in tutte le colonne
NOT NULL
venga inserito un valore esplicito.
-
Utilizzate i valori predefiniti
-
Ogni volta che specificate il vincolo
NOT NULL
per una colonna, se possibile specificate nella definizione della colonna un valore predefinito. Anche il codice dell'applicazione può fornire valori predefiniti. Ad esempio, il codice può controllare se una certa variabile in una stringa è
null
e assegnarle un valore prima di usarla per impostare il valore del parametro di un'istruzione.
-
Convalidate i dati immessi dall'utente
-
Controllate in anticipo i dati immessi dall'utente per assicurare che rispettino i limiti specificati dai vincoli, specialmente nel caso dei vincoli
NOT NULL
e
CHECK
. Ovviamente, è più difficoltoso controllare l'adesione al vincolo
UNIQUE
, poiché per farlo è necessario eseguire una query
SELECT
per determinare se i dati sono univoci.
-
Utilizzate i trigger
-
È possibile scrivere un trigger che convalidi (e magari sostituisca) i dati inseriti o esegua altre azioni al fine di correggere i dati non validi. La convalida e la correzione possono evitare il verificarsi di errori di vincolo.
Sotto molti punti di vista, gli errori concernenti i vincoli sono più difficoltosi da evitare degli altri tipi di errori. Fortunatamente esistono diverse strategie che consentono il recupero dagli errori di vincolo in modi che non rendono instabile o inutilizzabile l'applicazione.
-
Utilizzate gli algoritmi di conflitto
-
Quando si definisce un vincolo su una colonna, e quando si crea un'istruzione
INSERT
o
UPDATE
, si può scegliere di specificare un algoritmo di conflitto che definisce l'azione eseguita dal database al verificarsi della violazione di un vincolo. Il motore del database può eseguire diverse azioni possibili: può fare terminare una singola istruzione o un'intera transazione, può ignorare l'errore o può anche rimuovere i dati meno recenti e sostituirli con i dati che il codice sta tentando di memorizzare.
Per ulteriori informazioni, vedete la sezione “ON CONFLICT (algoritmi di conflitto)” in
Supporto di SQL nei database locali
.
-
Fornite un feedback correttivo
-
Il set di vincoli che può influenzare un certo comando SQL può essere identificato in anticipo. È di conseguenza possibile prevedere gli errori di vincolo che possono essere provocati da una certa istruzione e costruire la logica dell'applicazione in modo tale da essere in grado di reagire a tali errori. Ad esempio, supponiamo che l'applicazione comprenda una maschera per l'immissione dei dati relativi ai nuovi prodotti. Se la colonna del nome del prodotto nel database è definita con un vincolo
UNIQUE
, l'inserimento nel database di una riga per un nuovo prodotto può provocare un errore di vincolo. Di conseguenza l'applicazione è progettata in modo da prevedere tale errore. Quando si verifica l'errore, l'applicazione avverte l'utente che il nome del prodotto specificato è già in uso e chiede di scegliere un nome diverso. Un'altra risposta possibile è quella di consentire all'utente di visualizzare le informazioni riguardanti l'altro prodotto che ha lo stesso nome.
|
|
|