Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

I cicli nelle stored pocedures di MySQL

Una panoramica delle principali possibilità per eseguire cicli di codice all'interno di stored procedures di MySQL: cicli while, cicli repeat e cicli Loop
Una panoramica delle principali possibilità per eseguire cicli di codice all'interno di stored procedures di MySQL: cicli while, cicli repeat e cicli Loop
Link copiato negli appunti

Tecnicamente per ciclo o loop si intende un costrutto che determina la ripetizione di una o più istruzioni fino a quando una determinata condizione risulta soddisfatta o vera. I cicli sono molto utilizzati sia nei linguaggi di programmazione che in quelli di scripting e possono essere sfruttati anche per la definizione di Stored Procedures.

Per la generazione di loop nelle Stored Procedures abbiamo a disposizione tre standard:

  • cicli basati su WHILE;
  • cicli basati su REPEAT;
  • cicli basati su LOOP;
  • Cicli WHILE ..AND WHILE

    Un ciclo WHILE consente la ripetizione di istruzioni fino a quando una determinata condizione questa risulta vera. La sintassi utilizzata per un ciclo WHILE è molto semplice:

    WHILE condizione DO
        statements
    END WHILE
    

    Dove condizione determina l'iterazione del ciclo fino a quando rimane vera, mentre statements rappresenta un numero variabile di istruzioni che devono essere eseguite ad ogni iterazione; le iterazioni spesso agiscono direttamente sul valore associato alla condizione tanto da modificarlo influendo sugli esiti stessi del ciclo.

    Vediamo un semplice esempio:

    CREATE PROCEDURE proc () 
    BEGIN 
     DECLARE var INT; 
     SET var = 0; 
     WHILE var < 10 DO 
      INSERT INTO tbl VALUES (var); 
      SET var = var + 1; 
     END WHILE; 
    END; //
    

    Scomponiamo il codice appena proposto:

    • innanzitutto abbiamo definito il nome proc()
    • abbiamo poi aperto il blocco di istruzioni della stored procedure tramite il delimitatore BEGIN
    • è stata quindi introdotta una variabile (var INT
    • il valore iniziale della variabile è stato settato come pari a zero;
    • è stato quindi inizializzato un ciclo WHILE
    • con il comando DO
    • END WHILE
    • END; // BEGIN...END //

    La stored procedure che abbiamo definito non prevede il passaggio di parametri in chiamata, quindi per poter essere utilizzata basterà un riferimento al nome:

    mysql> CALL proc()//
    Query OK, 1 row affected (0.00 sec)
    

    La chiamata appena descritta potrà essere utilizzata per tutte le altre procedure descritte nel corso di questa trattazione.

    Diversamente da quello che si potrebbe aspettare, l'output prodotto da MySQL riporterà il risultato dell'interrogazione a carico di una sola riga ("1 row affected"); non si tratta di un errore, infatti, nella restituzione della risposta, il server prenderà in considerazione soltanto l'ultimo inserimento effettuato.

    Cicli con REPEAT ..END REPEAT

    Un ciclo basato su REPEAT funziona praticamente nello stesso modo di un loop basato su WHILE, vi è però una fondamentale differenza: mentre con WHILE la condizione viene definita (e quindi presa in considerazione) prima dell'istruzione da iterare, con REPEAT succede esattamente il contrario.

    Quindi in questo caso per i cicli basati su REPEAT dovremo utilizzare una sintassi simile alla seguente:

    REPEAT
        statements
    UNTIL condizione
    END REPEAT
    

    Quindi, "traducendo" letteralmente dal linguaggio SQL abbiamo qualcosa come "ripeti le istruzioni fino a quando (UNTIL) la condizione è vera, dopodiché interrompi l'iterazione (END REPEAT)".

    Vediamo di seguito un semplice esempio:

    CREATE PROCEDURE proc () 
    BEGIN 
     DECLARE var INT; 
     SET var = 0; 
     REPEAT 
      INSERT INTO tbl VALUES (var); 
      SET var = var + 1; 
      UNTIL var >= 10 
     END REPEAT; 
    END; //
    

    Anche in questo caso si è proceduto inizialmente alla definizione del nome della stored procedures, si nota subito come per essa non sia stato previsto alcun parametro; segue poi il delimitatore BEGIN che racchiude l'unico blocco di istruzioni della procedura e l'introduzione di una variabile (inizialmente pari a zero) che assumerà diversi valori sulla base delle iterazioni del ciclo.

    REPEAT è la clausola che inizializza il blocco di istruzioni relativo al ciclo vero e proprio, ad essa seguono le istruzioni che dovranno essere eseguite durante le iterazioni previste dal ciclo sulla base della condizione introdotta successivamente. Nel caso specifico le istruzioni non sono altro che un semplice statement per l'inserimento e un incremento unitario della variabile.

    UNTIL è invece la chiave che introduce la nostra condizione, essa stabilisce infatti che le istruzioni previste dal ciclo dovranno essere ripetute fino a quando il valore della variabile sarà maggiore o uguale a 10. Da notare come dopo l'istruzione UNTIL e la condizione introdotta non sia stato utilizzato il punto e virgola.

    REPEAT è un costrutto non nuovo a chi utilizza MySQL, si tratta infatti anche del nome di una funzione che permette di ripetere delle stringhe un numero predefinito di volte, creando appunto dei semplici cicli.

    Se infatti analizziamo per esempio l'istruzione seguente:

    SELECT REPEAT("stored procedure", 9);
    

    Questa ci permetterà di stampare 9 volte di seguito la stringa "stored procedure".

    Ciclo con LOOP ..END LOOP

    Il ciclo basato su LOOP si differenzia sia dal ciclo WHILE sia da quello REPEAT per via del fatto che non presenta una condizione né all'inizio né alla fine. La sintassi fondamentale di un ciclo basato su LOOP è semplicissima:

    LOOP
        statements
    END LOOP
    

    Per il controllo del flusso di un ciclo LOOP sono disponibili due istruzioni: LEAVE e ITERATE; mentre la prima svolge la funzione di abbandonare il flusso di iterazioni corrente, la seconda significa letteralmente "ripeti ancora il ciclo".

    Vediamo di seguito un semplice esempio:

    CREATE PROCEDURE proc () 
    BEGIN 
     DECLARE var INT; 
     SET var = 0; 
     loop_label: LOOP 
      INSERT INTO tbl VALUES (var); 
      SET var = var + 1; 
       IF var >= 10 THEN 
        LEAVE loop_label; 
       END IF; 
     END LOOP; 
    END; // 
    

    Anche il ciclo appena proposto presenta alcune similitudini con gli esempi analizzati in precedenza: il primo passaggio è ancora una volta quello relativo all'introduzione del nome della procedura seguito dalla creazione del blocco di istruzioni e dalla definizione di una variabile.

    La parte relativa al ciclo viene introdotta grazie al costrutto loop_label: LOOP a cui seguono le istruzioni da iterare fino alla fine del ciclo stesso; troviamo quindi un costrutto condizionale (IF...THEN) che impone l'uscita dal ciclo (LEAVE loop_label) nel momento in cui la variabile precedentemente dichiarata assume un valore maggiore o uguale a 10.

    La parte finale della stored procedure è naturalmente dedicata alla chiusura dei diversi blocchi di istruzione annidati, per cui vengono chiusi rispettivamente il costrutto condizionale (END IF), il ciclo stesso (END LOOP) e la stored procedure (END; //).

    In pratica nel ciclo LOOP appena analizzato abbiamo trovato un costrutto IF utilizzato come alternativa ad una condizione; all'interno del costrutto condizionale è stata invece inserita un'istruzione LEAVE che in pratica significa "esci dal ciclo".

    Etichettamento dei cicli

    L'inserimento di una label per un ciclo consente di isolare un gruppo di istruzioni ad esso riferito, con essa non facciamo altro che "etichettare" e quindi dare un nome al ciclo stesso. loop_label, utilizzata per l'esempio precedente, è quindi un'etichetta che può essere sostituita con un'altra predefinita dall'utente, è però importante che per la chiusura di un blocco di istruzioni riguardante un ciclo venga utilizzata la stessa label introdotta in apertura:

    CREATE PROCEDURE proc () 
    label_a: BEGIN 
     label_b: WHILE 0 = 1 DO LEAVE label_b;
     END WHILE label_b; 
     label_c: REPEAT LEAVE label_c; UNTIL 0 =0 
     END REPEAT label_c ; 
     label_d: LOOP LEAVE label_d; 
     END LOOP label_d ; 
    END label_a ; //
    

    Nell'esempio appena esposto l'itero blocco di istruzioni relativo alla procedura viene etichettato con label_a, è logico quindi che la chiusura del blocco stesso faccia riferimento alla stessa etichetta; succede la medesima cosa per quanto riguarda ogni ciclo contenuto all'interno del blocco BEGIN .. END, per cui all'etichettamento del ciclo WHILE come Label_b corrisponderà un riferimento in chiusura a Label_b e così via.

    Vediamo ora un esempio di ciclo LOOP basato sull'introduzione della clausola ITERATE:

    CREATE PROCEDURE proc () 
    BEGIN 
     DECLARE var INT; 
     SET var = 0; 
     loop_label: LOOP 
      IF var = 5 THEN 
       SET var = var + 1; 
       ITERATE loop_label; 
      END IF; 
     INSERT INTO tbl VALUES (var); 
     SET var = var + 1; 
     IF var >= 10 THEN 
      LEAVE loop_label; 
     END IF; 
    END LOOP; 
    END; //
    

    In questo caso, dopo l'etichettamento del loop abbiamo un blocco di istruzioni basato sul costrutto condizionale IF, al verificarsi della condizione non avviene un'uscita dal ciclo come nel caso di LEAVE ma una successiva iterazione imposta dalla clausola ITERATE; si chiude quindi il primo blocco IF ..END IF e si passa a delle nuove istruzioni da iterare, queste ultime verranno ripetute fino a quando verrà soddisfatta la condizione prevista dal secondo blocco IF ..END IF dopodiché potrà avvenire la definitiva uscita dal ciclo attraverso l'introduzione della clausola LEAVE.

Ti consigliamo anche