WHILE
Оператор WHILE
Оператор WHILE виконує цикл і має наступний синтаксис:
[label:] while search_condition DO
statement_list
END while [label]
Цикл WHILE виконує оператори statement_list до тих пір, поки умова search_condition істинна. При кожній ітерації умова search_condition перевіряється, і якщо при черговій перевірці воно буде хибним (0), цикл завершить своє виконання. Це означає, що якщо умова search_condition хибна з самого початку, цикл не виконає жодної ітерації.
Якщо в циклі потрібно виконати більше одного оператора, не обов'язково укладати, їх у блок BEGIN ... END, т. к. цю функцію виконує сам оператор WHILE. Виведемо 3 рази поточну дату за допомогою циклу WHILE (приклад).
Приклад:
CREATE PROCEDURE NOW5()
LANGUAGE SQL
BEGIN
DECLARE i INT DEFAULT 3;
WHILE i > 0 DO
SELECT NOW();
SET i = i - 1;
END WHILE;
END //
CALL NOW5()//
NOW()
2005-07-18 12:36:59
NOW()
2005-07-18 12:36:59
NOW()
2005-07-18 12:36:59
Перший оператор в циклі WHILE виводить поточну дату, а другий віднімає з локальної змінної i одиницю. Якщо одиницю не віднімати, то утворюється нескінченний цикл, з якого процедура ніколи не вийде, а буде марно навантажувати сервер, поки сеанс з ним не припиниться. Варто дуже уважно проектувати цикли, щоб запобігти нескінченні цикли.
У прикладі нижче представлений код збереженої процедури, яка виводить поточну дату num число раз, де num - параметр, що задається користувачем.
Приклад:
CREATE PROCEDURE NOWN (IN num INT)
LANGUAGE SQL
BEGIN
DECLARE i INT DEFAULT 0;
IF (num > 0) THEN wet : WHILE i < num DO SELECT NOW();
SET i = i + 1;
END WHILE wet;
ELSE
SELECT 'Помилкове значення параметра';
END IF;
END //
CALL NOWN(2)//
NOW ()
2005-07-18 12:51:27
NOW ()
2005-07-18 12:51:27
Як видно з попереднього прикладу, цикл WHILE іменований міткою wet. Мітка в циклі призначена не тільки для того, щоб полегшити читання коду при дуже довгих циклах, вона дозволяє здійснювати достроковий вихід з циклу.
Для дострокового виходу з циклу призначений оператор LEAVE, який має наступний синтаксис:
LEAVE label
Оператор LEAVE припиняє виконання блоку, позначеного міткою label.
Зауваження:
- Оператор LEAVE еквівалентний оператору break в С-подібних мовах програмування
Процедура NOWN () має недолік - якщо задати дуже велике значення аргументу num, можна створити псевдобескінечний цикл, який дозволить зловмиснику завантажити сервер марною роботою. Для запобігання такої ситуації можна скористатися оператором LEAVE, який припинить виконання никла після досягнення критичної числа ітерацій. У лістингу нижче наводиться приклад збереженої процедури, де число ітерації обмежена двома.
Приклад:
CREATE PROCEDURE NOWN (IN num INT)
LANGUAGE SQL
BEGIN
DECLARE i INT DEFAULT 0;
IF (num > 0) THEN
wet : WHILE i < num DO
IF i > 2 THEN LEAVE wet;
END IF;
SELECT N0W();
SET i = i + 1;
END WHILE wet;
ELSE
SELECT 'Помилкове значення параметра';
END IF;
END //
CALL NOWN(10)//
NOW()
2005-07-18 12:51:27
NOW()
2005-07-18 12:51:27
Умова if i> 2 then leave wet; перевіряє, чи не перевищило значення лічильника i число 2, і якщо це так, відбувається припинення циклу while. Використання міток дозволяє точно вказати, який цикл необхідно перервати. Якщо є вкладений цикл, можна явно вказати, який з двох циклів потрібно перервати (приклад).
Приклад:
first : WHILE i < num DO
second : WHILE j < num DO
IF i > 2 && j > 2 THEN LEAVE first;
END IF;
SELECT NOW();
SET j = j + 1;
END WHILE second;
SET i = i + 1;
END WHILE first;
При досягненні умови i> 2 & & j> 2 оператор LEAVE перерве не вкладений цикл second, а зовнішній цикл first, т. к. мітка зовнішнього циклу явно вказана після оператора.
При використанні дострокового виходу LEAVE можна навіть використовувати нескінченні цикли, тому що рано чи пізно зовнішній цикл буде завершений (приклад).
Приклад:
first : WHILE 1 DO
second : WHILE 1 DO
IF i > 2 && j > 2 THEN LEAVE first;
END IF; SELECT NOW();
SET j = j + 1;
END WHILE second;
SET i - i + 1;
END WHILE first;
Цифра 1 в умові циклу завжди буде істинною і цикл не припиниться до тих пір, поки його не перерве оператор LEAVE.