Le stored procedures ci permettono di memorizzare all'interno dei nostri database dei veri e propri sotto-programmi destinati ad essere richiamati per l'esecuzione di determinate operazioni; esse contengono i comandi SQL che dovranno essere eseguiti, in questo modo non sarà necessario riscriverli ogni volta che si deve inviare al DBMS una determinata interrogazione.
Nelle stored procedures acquisiscono una particolare importanza i costrutti per il controllo del flusso dei dati; grazie ad essi sarà infatti possibile inserire delle condizioni sulla base dei diversi eventi che potranno verificarsi durante il trattamento dei dati, rendendo i nostri sub-programmi ancora più raffinati. In questo breve articolo vedremo come utilizzare i costrutti per il flow control e quali elementi entrano in gioco durante l'introduzione delle condizioni.
Le variabili
Le variabili, molto utilizzate nei linguaggi di programmazione e di scripting, sono dei veri e propri "contenitori di informazioni"; ad esse potrà essere associato un valore e la variabile diventerà rappresentazione di quest'ultimo.
Vediamo un semplice esempio di definizione di una varabile all'interno di una procedura:
CREATE PROCEDURE p () BEGIN DECLARE x INT; DECLARE y INT; SET x = 8; SET y = 8; INSERT INTO tbl VALUES (x); SELECT field * x FROM tbl WHERE field >= y; END; //
La procedura del nostro esempio non accetta come argomento la definizione di una variabile, all'interno delle parentesi tonde non viene infatti passato alcun argomento; vengono invece definite due variabili (x
ed y
) all'interno del blocco di istruzioni BEGIN
/ END
e ad esse viene associato un tipo di dato e un valore.
I nomi delle variabili e il tipo di dato ad esse associato vengono introdotti tramite il comando DECLARE
, mentre abbiamo utilizzato SET
per stabilire quale valore dovesse essere associato alle variabili.
Una volta definite le varabili queste sono state utilizzate per l'esecuzione di due differenti istruzioni, un comando per l'inserimento e una query di selezione.
Nel comando per l'INSERT
la variabile x
rappresenta il valore 8
ad essa associato; stesso discorso per quanto riguarda il valore y
usato come argomento per il confronto nella clausola WHERE
della SELECT
.
La possibilità di definire delle variabili assume un ruolo particolarmente importante in quanto una volta che esse vengono dichiarate è possibile riutilizzarle in qualunque momento tramite una semplice operazione di chiamata della procedura che vedremo tra poco.
Alle variabili è possibile associare anche un valore di default grazie all'utilizzo della clausola omonima; quindi una procedura come quella creata nel nostro primo esempio avrebbe potuto essere definita anche in questo modo:
CREATE PROCEDURE p () BEGIN DECLARE x, y INT DEFAULT 8; INSERT INTO tbl VALUES (x); SELECT field * x FROM tbl WHERE field >= y; END; //
Nonostante questa seconda procedura sia concettualmente identica alla prima, possiamo notare un importante elemento di novità: due variabili sono state definite tramite un unico comando DECLARE
e ad esse è stato associato un valore di default valido per entrambe.
Indipendentemente dall'utilizzo o meno di valori di default, la procedura definita potrà essere richiamata semplicemente facendo riferimento al suo nome utilizzato come argomento del comando CALL
:
mysql> CALL p () //
Il risultato sarà quindi determinato dal valore del field
, unico elemento suscettibile di variazione, in quanto conosciamo a priori il valore delle due variabili definite.
Utilizzo delle condizioni all'interno delle procedure
Ora che sappiamo come definire le variabili, vediamo come è possibile utilizzarle all'interno di costrutti per il controllo del flusso; le variabili assumo un ruolo molto importante in questo tipo di istruzioni, infatti le condizioni possono basarsi proprio sul valore assunto da esse influenzando il manifestarsi degli eventi. Facciamo un esempio:
CREATE PROCEDURE p (IN par INT) BEGIN DECLARE var INT; SET var = par + 1; IF var = 0 THEN INSERT INTO tbl VALUES (10); END IF; IF par = 0 THEN UPDATE tbl SET field = field + 1; ELSE UPDATE tbl SET field = field + 2; END IF; END; //
Chi ha già una certa conoscenza in merito ai linguaggi di programmazione e di scripting non avrà certo difficoltà a comprendere i meccanismi messi in atto dalla procedura mostrata che riassumiamo in questo elenco:
- Viene creata la procedura, nel nostro caso denominata semplicemente
p
; ad essa viene passato come argomento un parametro (par
) a cui viene associato un tipo di dato intero; a passare il parametro all'interno della procedura è la keywordIN
. - Viene inserito il delimitatore iniziale del blocco di istruzioni (
BEGIN
) e definita la prima variabile; il valore di quest'ultima dovrà essere pari al valore del parametro di funzione più1
. - Viene introdotta l'istruzione condizionale
IF
(letteralmente "se.."); essa stabilisce una condizione sulla base del valore assunto dalla variabile; nel caso specifico abbiamo che: se il valore della variabile è pari a0
(IF var = 0
), allora (THEN
) dovrà essere eseguita un'istruzioneINSERT
di un valore pari a10
; la clausolaTHEN
stabilisce infatti quale evento debba verificarsi nel caso in cui si verifichi la condizione stabilita daIF
. - Il primo blocco di condizione viene quindi chiuso tramite il delimitatore
END IF
; attenzione però! Con questo non si chiude il blocco di istruzioni relativo alla procedura. - Infatti, viene inserito un secondo blocco di condizione: esso stabilisce che se il valore del parametro è pari a
0
, allora si dovrà verificare un aggiornamento (UPDATE
) del campofield
che subirà un incremento unitario. - Diversamente (
ELSE
), se la condizione stabilita non dovesse verificarsi, l'incremento non sarà più pari a1
ma a2
;ELSE
infatti stabilisce un'alternativa praticabile nel caso in cui la condizione argomento diIF
non dovesse essere soddisfatta.ELSE
non è una clausola obbligatoria (non è infatti presente nel primo blocco di condizione), può comunque essere introdotta per incrementare le possibilità di controllo sul flusso dei dati. - A questo punto, può essere chiuso sia il secondo blocco di condizione, che l'intero blocco di istruzioni del sotto-programma.
In questo caso, a differenza delle procedure per la dichiarazione delle variabili descritte nei primi due esempi, il nostro sotto-programma p
dovrà essere richiamato specificando un parametro numerico intero da passare alla funzione:
mysql> call p (n) //
Il valore di questo parametro avrà un ruolo fondamentale nella soddisfazione o meno delle condizioni definite all'interno del blocco.
Flow control con CASE e WHEN
Oltre ai blocchi condizionali basati su IF
abbiamo un'altra tipologia di costrutti per il controllo del flusso che può essere impiegata nella creazione di stored procedures. Si tratta delle istruzioni basate sulle clausole CASE
e WHEN
; vediamone subito un semplice esempio:
CREATE PROCEDURE p (IN par INT) BEGIN DECLARE var INT; SET var = par + 1; CASE var WHEN 0 THEN INSERT INTO tbl VALUES (10); WHEN 1 THEN INSERT INTO tbl VALUES (11); ELSE INSERT INTO tbl VALUES (12); END CASE; END; //
La logica alla base di questa routine non è molto differente da quella presentata nell'esempio precedente; vediamone nel particolare i singoli elementi costituivi:
- Abbiamo creato innanzitutto una procedura chiamata
p
a cui è stato passato come argomento tramiteIN
un parametro numerico intero; il valore di questo parametro non necessita di essere determinato a priori. - Una volta definito il nome della procedura e il relativo argomento, siamo passati alla delimitazione del blocco di istruzioni tramite
BEGIN
e all'uso diDECLARE
per l'introduzione della variabile, ad essa è stato associato un valore pari all'incremento unitario del parametro di input della procedura. CASE
è un'istruzione condizionale che svolge una funzione molto simile a quella di costrutti comeSelect…
Case
per Visual Basic oSwitch()
per linguaggio C e derivati, permette infatti al DBMS di effettuare verifiche su più campi. A differenza diIF
che presuppone una condizione,CASE
ne introduce un numero indefinito, o meglio definito arbitrariamente dall'utente.- Nella routine abbiamo stabilito che
CASE
avrà come parametro il valore associato alla variabile durante l'esecuzione della procedura. - A questo punto entra in gioco
WHEN
(letteralmente "quando..") che introduce le diverse condizioni. THEN
si occuperà di fare in modo che si verifichino gli eventi associati alle diverse condizioni definite.ELSE
introduce un'alternativa, questa avrà luogo nel caso in cui non si verifichi alcuna delle condizioni previste per l'argomento (var
) passato aCASE
.- Stabilite le istruzioni di condizione abbiamo chiuso il blocco
CASE
(END CASE
) e quello relativo alla procedura.
Osservando quanto esposto nel nostro esempio possiamo isolare il codice relativo al blocco CASE
:
CASE var WHEN 0 THEN INSERT INTO tbl VALUES (10); WHEN 1 THEN INSERT INTO tbl VALUES (11); ELSE INSERT INTO tbl VALUES (12); END CASE;
In pratica l'istruzione comunica al Database Manager che il termine di paragone è il valore di var
, quando (WHEN
) questo valore è pari a 0
allora (THEN
) l'inserimento dovrà essere pari a 10
; quando esso è pari a 1
avremo un VALUE
uguale a 11
; diversamente (ELSE
) l'inserimento sarà pari a 12
per tutti i valori di var
diversi da 0
e 1
.
Conclusioni
In questa breve guida ci siamo occupati dell'utilizzo dei costrutti per il controllo del flusso di dati nelle Stored Procedures; per far questo abbiamo introdotto l'argomento relativo alle variabili passando poi al loro utilizzo all'interno dei blocchi di condizione. Questo discorso potrà essere ampliato con una trattazione riguardante l'utilizzo dei "cicli" nelle routines, argomento che approfondiremo in una prossima trattazione.