Thursday 27th of April 2017 10:28:59 PM MySQL Stored Procedures: Part 2

Loops: WHILE

Thursday 27th of April 2017 10:28:59 PM

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)

Figure 6-5

Figure 6-5. Setting different colors for different hyperlink classes

This sort of thing simply isn't possible with the old BODY attributes. Furthermore, if you're going to use the BODY attributes, you have to define them in each and every document. If you ever decide to change those values ...well, you have a lot of files to edit, don't you? On the other hand, if you set up these colors as an external style sheet, and then link all of your pages to the style sheet, then you only have to edit one file in order to change the text colors of 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
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.

30px tall.

Nonetheless, an inline replaced element still has a value forline-height. Why? In order to be able to correctlyposition the element if it's been vertically aligned. Recallthat, percentage values for vertical-align arecalculated with respect to an element's line height. Thus:

P {line-height: 18px;}IMG {vertical-align: 50%;}
required to reflow previous content to accommodate things whichhappen later in the document. In other words, if an image is floatedup into a previous paragraph, it may simply overwrite whatever wasalready there. On the other hand, the user agent may handle thesituation by flowing content around the float, even though doing soisn't required behavior. Either way, it's probably a badidea to count on a particular behavior, which makes the utility ofnegative margins on floats somewhat limited. Hanging floats areprobably fairly safe, but trying to push an element upward on thepage is a generally bad idea.