27
SQL STORED PROCEDURES + STORED FUNCTIONS MySQL 5.5

Sql stored procedures

Embed Size (px)

Citation preview

SQL STORED PROCEDURES

+ STORED FUNCTIONS

MySQL 5.5

MYSQL E LE STORED PROCEDURES

Una frase che una volta si sentiva spesso.

“Bello MySQL! Peccato che non supporti le stored procedures… Se ce le avesse lo userei anch’io.”

Ma cosa sono le stored procedure? E perché tanti ne sentivano la mancanza?

Un esempio pratico collegato al database World, predefinito in MySQL.

DELIMITER //

CREATE PROCEDURE NumCittà (IN Lingua CHAR(30), OUT NumCINTEGER)

BEGIN

SELECT COUNT(*) INTO NumC

FROM countrylanguage AS Cl, country AS Cn, City AS Cy

WHERE Cl.CountryCode = Cn.Code

AND Cy.CountryCode = Cn.Code

AND Cl.Language = Lingua;

END; //

DELIMITER ;

MYSQL E LE STORED PROCEDURES

Le istruzioni della slide precedente creano un procedura per la base di dati World.

Questa procedura, una volta creata, può essere richiamata in qualsiasi momento dal prompt dei comandi, attualizzando i suoi parametri.

Es.

CALL NumCittà(“Inglese”,@Num);

SELECT @Num AS Città_Inglese;

In questo modo le istruzioni della Stored Procedure NumCittàvengono eseguite assegnando al parametro di ingresso Lingua il valore “Inglese”.

Il risultato dell’esecuzione viene reso disponibile nella variabile @Num.

MYSQL E LE STORED PROCEDURES

Esaminiamo più nel dettaglio l’esempio appena proposto.

DELIMITER //

Questa istruzione modifica l’indicatore di fine istruzione per MySQL.

Di default il delimitatore è il carattere “;”.

All’interno di una stored procedure però sono presenti più istruzioni, quindi perché MySQL interpreti correttamente l’istruzione CREATE PROCEDURE occorre cambiare il delimitatore.

Nel nostro caso si sceglie la combinazione “//”, ma avremmo potuto scegliere qualsiasi altra combinazione di caratteri

Al termine della stored procedure si ripristina il delimitatore standard con l’istruzione: DELIMITER ;

MYSQL E LE STORED PROCEDURES

CREATE PROCEDURE NumCittà (IN Lingua CHAR(30), OUT NumC INTEGER)

L’intestazione della procedura consente di definire alcune caratteristiche essenziali:

• Nome della procedura

Il nome della procedura servirà per richiamare la procedura stessa dal prompt dei comandi di MySQL.

• Elenco dei parametri

I parametri indicano le informazioni che occorre fornire alla procedura affinché questa possa essere eseguita, e quelle che la procedura fornirà come risultato.

IN parametri di ingresso

OUT parametri di uscita

INOUT parametri bidirezionali

Nel nostro caso la procedura riceve in ingresso una stringa Lingua e produce in uscita un numero intero NumC.

MYSQL E LE STORED PROCEDURES

BEGIN

...

END; //

Le due parole chiave BEGIN e END racchiudono il

corpo della funzione.

Come si vede l’istruzione CREATE PROCEDURE

termina con il delimitatore “//”

Il delimitatore “;” invece indica il termine di ogni

istruzione all’interno del corpo della procedura e il termine del blocco BEGIN … END (non il termine

dell’istruzione CREATE)

MYSQL E LE STORED PROCEDURES

SELECT COUNT(*) INTO NumC

FROM countrylanguage AS Cl, country AS Cn, City AS Cy

WHERE Cl.CountryCode = Cn.Code

AND Cy.CountryCode = Cn.Code

AND Cl.Language = Lingua;

Si tratta come si vede di una query normale

Ci sono però due particolari importanti:

• Il risultato della SELECT viene memorizzato nel parametro di uscita NumC

• Il valore di Cl.Language viene ricavato dal parametro di ingresso Lingua

In sostanza questa query determina in quante città si parla una certa lingua

MYSQL E LE STORED PROCEDURES

CALL NumCittà(“Inglese”,@Num);

Con questa sintassi viene eseguita dal prompt dei comandi di MySQL la procedura NumCittà

Al parametro lingua viene assegnato il valore “Inglese”

Il risultato della query viene memorizzato nella variabile @Num

SELECT @Num AS Città_Inglese;

Il valore della variabile @Num viene infine visualizzato col nome Città_Inglese.

VARIABILI IN MYSQL

MySQL consente di memorizzare un valore in una variabile definita dall’utente

Il valore può così essere utilizzato da istruzioni successive a quelle in cui è stato assegnato alla variabile

Le variabili sono associate alla connessione in cui vengono create

Una variabile definita da un client non viene vista da un altro client

Al termine della connessione vengono tutte eliminate

Nomi delle variabili Iniziano con @

Possono contenere lettere e numeri

Possono contenere i caratteri “.”, “_” e “$”

VARIABILI IN MYSQL

Assegnamento di un valore a una variabile SET @var_name = expr [, @var_name = expr] ...

Si può utilizzare anche il simbolo :=

SET @t1=1, @t2=2, @t3:=4;

SELECT @t1, @t2, @t3, @t4 := @t1+@t2+@t3;

+------+------+------+--------------------+

| @t1 | @t2 | @t3 | @t4 := @t1+@t2+@t3 |

+------+------+------+--------------------+

| 1 | 2 | 4 | 7 |

+------+------+------+--------------------+

All’interno della SELECT è obbligatorio utilizzare il simbolo :=

Non si deve mai assegnare un valore a una variabile e utilizzarlo all’interno della stessa istruzione MySQL non garantisce il risultato

Possono verificarsi effetti indesiderati

VARIABILI IN MYSQL

A una variabile si possono assegnare solo i seguenti tipi di dato

Numeri interi (INTEGER)

Numeri con a virgola fissa (DECIMAL)

Numeri a virgola mobile (FLOAT, DOUBLE)

Stringhe di caratteri NULL

Tutti i tipi non ammessi vengono convertiti nei tipi ammessi

La conversione può essere forzata con l’istruzione CAST

SET @v1 = b'1000001';

SET @v2 = CAST(b'1000001' AS UNSIGNED), @v3 = b'1000001'+0;

SELECT @v1, @v2, @v3;

+------+------+------+

| @v1 | @v2 | @v3 |

+------+------+------+

| A | 65 | 65 |

+------+------+------+

VARIABILI IN MYSQL

Le variabili trovano il loro utilizzo nelle espressioni all’interno delle query

Es.

SET @var = 15;

SELECT *

FROM Table AS T

WHERE T.Campo = @var;

Non possono essere utilizzate negli identificatori di campi e tabelle, o al posto di parole chiave

Es. (non valido)

SET @var1 = ‘Table’;

SET @var2 = ‘SELECT’

@var2 *

FROM @var1 AS T

WHERE T.Campo = 15;

VARIABILI IN MYSQL

C’è una sola eccezione a questa regola Si costruisce una query in una variabile stringa con l’istruzione PREPARE

La si esegue con l’istruzione EXECUTE

Es.SET @c = "c1";

SET @s = CONCAT("SELECT ", @c, " FROM t");

PREPARE stmt FROM @s;

EXECUTE stmt;

+----+

| c1 |

+----+

| 0 |

+----+

| 1 |

+----+

2 rows in set (0.00 sec)

DEALLOCATE PREPARE stmt;

SINTASSI DI UNA STORED PROCEDURE

La sintassi generale di una stored procedure è la

seguente.

CREATE PROCEDURE nome ([<parametro>[,...]])

[SQL SECURITY { DEFINER | INVOKER }]

BEGIN

<istruzioni>

END; //

La sintassi di ciascun parametro è invece la seguente:

[ IN | OUT | INOUT ] <nome> <tipo>

DICHIARAZIONE DI VARIABILI

All’interno di una stored procedure è possibile

dichiarare variabili

DECLARE <nome> <tipo> [DEFAULT <valore>];

Si può assegnare valori alle variabili in due modi

SELECT <campo> INTO <variabile>

FROM ... ;

SET <variabile> = <espressione>;

Un particolare tipo di variabile sono i CURSORI

DECLARE <nome> CURSOR FOR <query> ;

LE VARIABILI CURSORI

Una variabile cursore serve per scorrere il risultato di una query caricandone i record progressivamente all’interno di opportune variabili

DECLARE a INT;

DECLARE b CHAR(50);

DECLARE cur CURSOR FOR

SELECT id, nome

FROM clienti

WHERE cat = <parametro>;

OPEN cur;

FETCH cur INTO a, b;

CLOSE cur;

Quando viene aperto, il cursore si posiziona sulla prima tupla del risultato dellaquery

Ogni volta che si effettua un FETCH, la tupla viene caricata nelle variabilispecificate dopo la parola chiave INTO.

La chiusura del cursore non è obbligatoria. MySQL chiude automaticamente i cursori al termine di una procedura.

LA STRUTTURA IF – THEN – ELSE

È possibile utilizzare una semplice struttura di

selezione

La sintassi è la seguente

IF <condizione> THEN

<istruzioni>

ELSE

<istruzioni>

END IF;

Come sempre la parte ELSE è facoltativa

LA STRUTTURA DI ITERAZIONE LOOP

Si tratta di un semplice costrutto per cicli illimitati

Sintassi:

<etichetta>: LOOP

<istruzioni>

END LOOP <etichetta>;

Per uscire dal ciclo:

LEAVE <etichetta>;

Per passare all’iterazione successiva:

ITERATE <etichetta>;

LA STRUTTURA DI ITERAZIONE LOOP

Es.

DELIMITER //

CREATE PROCEDURE SommaInt(IN p1 INT, OUT Sum INT)

BEGIN

DECLARE i INT;

SET Sum = 0;

SET i = 0;

label1: LOOP

SET i = i + 1;

SET Sum = Sum + i;

IF i < p1 THEN

ITERATE label1;

END IF;

LEAVE label1;

END LOOP label1;

END; //

DELIMITER ;

LA STRUTTURA DI ITERAZIONE REPEAT

Si tratta di un semplice costrutto per cicli limitati

Sintassi:

<etichetta>: REPEAT

<istruzioni>

UNTIL <condizione>

END REPEAT <etichetta>;

Il ciclo si interrompe quando la condizione diventa veraper la prima volta

La condizione viene valutata al termine di ogniiterazione

LA STRUTTURA DI ITERAZIONE REPEAT

Es.

DELIMITER //

CREATE PROCEDURE SommaInt(IN p1 INT, OUT Sum INT)

BEGIN

DECLARE n INT;

SET n = 0;

SET Sum = 0;

REPEAT

SET n = n + 1;

SET Sum = Sum + n;

UNTIL n = p1

END REPEAT;

END; //

CALL SommaInt(10,@Somma) //

SELECT @Somma //

+------+

| @x |

+------+

| 55 |

+------+

1 row in set (0.00 sec)

LA STRUTTURA DI ITERAZIONE WHILE

Si tratta di un semplice costrutto per cicli limitati

Sintassi:

<etichetta>: WHILE <condizione> DO

<istruzioni>

END WHILE <etichetta>;

Il ciclo si interrompe quando la condizione diventafalsa per la prima volta

La condizione viene valutata prima di ogniiterazione

LA STRUTTURA DI ITERAZIONE WHILE

Es.

DELIMITER //

CREATE PROCEDURE SommaInt(IN p1 INT, OUT Sum INT)

BEGIN

DECLARE i INT;

SET Sum = 0;

SET i = 0;

label1: WHILE i <= p1 DO

SET i = i + 1;

SET Sum = Sum + i;

END WHILE label1;

END; //

DELIMITER ;

DICHIARAZIONE DI HANDLER

Handler: gruppo di istruzioni da eseguire al verificarsi di particolari condizioni durante l’esecuzione di una procedura

Sintassi:

DECLARE <azione> HANDLER

FOR <condizione1> [, <condizione2>] ...

<istruzioni>;

Azioni EXIT Termina la procedura

CONTINUE Continua l’esecuzione

Condizioni <codice_errore_MySQL>

SQLSTATE [VALUE] <valore>

SQLWARNING

NOT FOUND

SQLEXCEPTION

CONDIZIONI PER GLI HANDLER

<codice_errore_MySQL> e SQLSTATE Elenco dei codici di errore e SQLSTATE di MySQL

SQLWARNING

Tutti i codici di errore che cominciano per ‘01’

NOT FOUND

Tutti i codici di errore che cominciano per ‘02’

SQLEXCEPTION

Tutti i codici di errore che NON cominciano per ‘00’, ‘01’, ‘02’

I codici che cominciano con ‘00’ non indicano un errore ma l’esecuzione corretta di un’operazione, e quindi non andrebbero mai utilizzati in un Handler

STORED FUNCTIONS

Simili alle Stored Procedures ma più semplici

Restituiscono un dato semplice Non possono restituire un insieme di tuple

Esempi di Stored Functions predefinite sono le funzioni di aggregazione

Sintassi:

CREATE FUNCTION <nome>([<parametro>[,...]])RETURNS <tipo>

[SQL SECURITY { DEFINER | INVOKER }]

BEGIN

<istruzioni>

END;

Parametri<parametro> <tipo>

SQL SECURITY

Per eseguire una qualsiasi istruzione su una base di dati è necessario che l’utente possieda i privilegi necessari

Per esempio non è detto che un utente abbia il permesso di inserire tuple in una tabella, oppure di cancellarle

La clausola SQL SECURITY permette di specificare chi deve possedere i privilegi necessari a eseguire tutte le istruzioni contenute in una stored procedure

DEFINER Chi ha creato la procedura deve possedere i permessi necessari a eseguirla

INVOKER Chi invoca la procedura deve possedere i permessi necessari a eseguirla