Thursday 14th of December 2017 08:56:07 AM MySQL Stored Procedures: Part 2

Loops: WHILE

Thursday 14th of December 2017 08:56:07 AM

Loops are a vital component of procedures - they allow the same portion of code to be repeated a number of time. WHILE loops, the first type of loop we are going to look at, continuously repeat a block while a particular condition is true.

WHILE condition DO
statement/s
END WHILE

Here is an example. Be careful when entering it though, and with all loops! Always create your procedures on a test server first. All novice (and some not so novice) programmers at one time or another create an infinite loop. If you had forgotten to increment var1 in the procedure, it would always stay as whatever you had passed to the procedure. If this were anything less than 20, the loop would continue indefinitely.

mysql> CREATE PROCEDURE sp_while(IN var1 INT)
BEGIN
WHILE (var1 < 20) DO
SELECT var1;
SET var1=var1+1;
END WHILE;
END|
Query OK, 0 rows affected (0.00 sec)
mysql> CALL sp_while(18)\G
*************************** 1. row ***************************
var1: 18
1 row in set (0.00 sec)
*************************** 1. row ***************************
var1: 19
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
mysql> CALL sp_while(22)\G
Query OK, 0 rows affected (0.00 sec)

Note that when we called the procedure, passing 22, no statements were executed, as the condition failed immediately.

REPEAT UNTIL

The other commonly used loop is the REPEAT UNTIL construct.

REPEAT
statement/s
UNTIL condition
END REPEAT

The statements are repeatedly performed until the condition is met. A difference to the WHILE loop is that the condition is only tested after the statements have been performed, so there is always at least one instance of the statements being run. Here is an example:

mysql> CREATE PROCEDURE sp_repeat(IN VAR1 INT)
BEGIN
REPEAT
SELECT var1;
SET var1=var1+1;
UNTIL var1>5
END REPEAT;
END|
Query OK, 0 rows affected (0.09 sec)
mysql> CALL sp_repeat(3)\G
*************************** 1. row ***************************
var1: 3
1 row in set (0.00 sec)
*************************** 1. row ***************************
var1: 4
1 row in set (0.00 sec)
*************************** 1. row ***************************
var1: 5
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
mysql> CALL sp_repeat(8)\G
*************************** 1. row ***************************
var1: 8
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)

Note, that even when we call the procedure with 8, which means that the condition evaluates to true (and exits the loop) the first time it is encountered, the SELECT statement is still executed once, as the condition is only tested at the end.

LABELS, LEAVES and LOOPS

Labels are simply text strings that are used to mark part of the procedure. They can simply play the role of comments, or be part of the logic, as we will see below in the LOOP construct. Here is an example of LABELS used to comment the start of a procedure. The label is begin1. This may not seem useful here, but complex statements can be deeply nested, and in that case, clear labels will make the logic easier to follow. They also play a vital logical role, as we will see later.

mysql> CREATE PROCEDURE sp_label()
begin1: BEGIN
END|
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE PROCEDURE sp_label2()
begin1: BEGIN
END begin1|
Query OK, 0 rows affected (0.00 sec)

In the second example, the end is also labeled. If an end label exists, it must match a start label of the same name. You can use LABELS before BEGIN, WHILE, REPEAT and LOOP (introduced below) statements, as well as the accompanying END statements, and also as targets for ITERATE statements (also introduced below).

A third kind of loop is the LOOP construct. This one does not test against a condition at either the start or the end of the loop. It continues looping until explicitly exited with a LEAVE statement, making it easy to get stuck in an infinite loop (as I did when creating this example). The LEAVE statement exits a block (which can include the procedure itself). Since there can be many nested constructs, it must also be accompanied by a label name to determine which block to leave.

label LOOP
statement/s
LEAVE label
statement/s
END LOOP

Here is an example:

mysql> CREATE PROCEDURE sp_loop(IN var1 INT)
BEGIN
loop1: LOOP
IF (var1 > 5) THEN
LEAVE loop1;
END IF;
SET var1=var1+1;
SELECT var1;
END LOOP;
END |
Query OK, 0 rows affected (0.00 sec)
mysql> CALL sp_loop(2)\G
*************************** 1. row ***************************
var1: 3
1 row in set (0.00 sec)
*************************** 1. row ***************************
var1: 4
1 row in set (0.00 sec)
*************************** 1. row ***************************
var1: 5
1 row in set (0.00 sec)
*************************** 1. row ***************************
var1: 6
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)

The LABEL name we used above is loop1, and the LEAVE statement explicitly left loop1. We did not make use of an end label.

ITERATE statements

Iterates can only appear within LOOP, REPEAT, and WHILE statements. They are followed by a LABEL name, and effectively direct control back to that LABEL. So, if they appear half-way through a loop, and they direct control back to the top of that loop, the rest of the loop will not be carried out (bear this logic in mind when testing, as it again opens the possibilities for infinite loops).

In this next example, we use a WHILE loop, and ITERATE back to the beginning of the loop if var1 is still less than 3.

mysql> CREATE PROCEDURE sp_while_iterate(IN var1 INT)
-> BEGIN
->  while_label: WHILE (var1 < 5) DO
->   SELECT CONCAT('starting the loop: var1 is: ',var1);
->   SET var1=var1+1;
->   IF (var1<3) THEN
->    ITERATE while_label;
->   END IF;
->   SELECT CONCAT('ending the loop: var1 is: ',var1);
->  END WHILE;
-> END|
Query OK, 0 rows affected (0.00 sec)
mysql> CALL sp_while_iterate(1)\G
*************************** 1. row ***************************
CONCAT('starting the loop: var1 is: ',var1): starting the loop: var1 is: 1
1 row in set (0.00 sec)
*************************** 1. row ***************************
CONCAT('starting the loop: var1 is: ',var1): starting the loop: var1 is: 2
1 row in set (0.00 sec)
*************************** 1. row ***************************
CONCAT('ending the loop: var1 is: ',var1): ending the loop: var1 is: 3
1 row in set (0.00 sec)
*************************** 1. row ***************************
CONCAT('starting the loop: var1 is: ',var1): starting the loop: var1 is: 3
1 row in set (0.00 sec)
*************************** 1. row ***************************
CONCAT('ending the loop: var1 is: ',var1): ending the loop: var1 is: 4

A related topic is the subject of backgrounds and their relationshipto floated elements that occur earlier in thedocument, which was also discussed in the previous chapter, as hasbeen illustrated in Figure 8-41.

Figure 8-41

Figure 8-41. Backgrounds "slide under" floated elements

Because the floated element is both within and without the flow, thissort of thing is bound to happen. What's going on? Well, thecontent of the paragraphs is being "displaced" by the 1 row in set (0.00 sec) *************************** 1. row *************************** CONCAT('starting the loop: var1 is: ',var1): starting the loop: var1 is: 4 1 row in set (0.00 sec) *************************** 1. row *************************** CONCAT('ending the loop: var1 is: ',var1): ending the loop: var1 is: 5 1 row in set (0.00 sec) Query OK, 0 rows affected (0.00 sec)

The first time through the loop, only starting the loop is displayed, as var1 is at 2 when the time comes to evaluate the IF condition, and the condition evaluates to true. The ITERATE sends control back to the start of the loop again. The second time through, var1 starts at 2, but is then incremented to 3, and the IF condition is false. The full loop is executed.

Conclusion

This week we introduced conditions and loops, two of the basic fundamental structures used in stored procedures. There is still more to come, so check back next month as we continue our series.

{clear: left;}. This can betranslated as "make sure that the left side of anH2 is clear of floating images" and is areplacement for the HTML construct<BRclear="left">. Figure 7-74shows the following declaration, which uses clearto prevent H2 elements from flowing past floatedelements to the left side:

In other words, if there are three values given for margin , the fourth (left) is copied from the second (right). If there are two values given, the fourth is copied from the second, and the third (bottom ) from the first (top ). Finally, if there is only one value given, then it's copied to all the others.

This simple mechanism allows authors to supply only as many values asdifferent sizes. Thus you might see something like the following,shown in Figure 5-29:

H1 {font-variant: small-caps;}P {font-variant: normal;}<H1>The Uses of font-variant</H1><P>The property <CODE>font-variant</CODE> is very interesting...</P>
Figure 5-29

Figure 5-29. Small caps in use