MySQL позволяет использовать курсоры (CURSORs) в хранимых процедурах. Эта конструкция позволяет организовать сложную обработку данных на стороне сервера привычным программисту способом, а именно — строка за строкой. Обработка данных на стороне MySQL может сократить время обработки данных, т.к. не нужно передавать данные из базы в программу и наоборот, как это часто происходит при работе с базой из PHP скрипта на веб-сервере.
Дальше мы разберем как объявить и работать с курсорами.
При работе с курсорами надо помнить, что они :
- нечувствительны к изменениям в базе; то есть после выполнения запроса, данные там статичны;
- работают только на чтение (readonly);
- просматривают результаты только в одном направлении и не могут «перескакивать» через строки.
Фазы жизни курсора
Курсоры объявляются в начале хранимой процедуры до выполнения каких либо операций.
1 2 3 4 5 |
//пара переменных для последующей выборки данных курсора DECLARE a, b INT; //объявляем курсор, выбирающий пары значений из некой тестовой таблицы DECLARE cur1 CURSOR FOR SELECT value_a, value_b FROM test.t1; |
Перед выборкой строк из курсора его нужно инициализировать (выполняется запрос)
1 |
OPEN cur1; |
Далее вы можете выбирать данные из курсора, строка за строкой.
1 2 3 4 5 6 7 8 |
//помещаем следующую пару значений в переменные a и b FETCH cur1 INTO a, b; //выполняем какие то манипуляции с данными IF a < b THEN ... ELSE ... END IF; |
Завершается работа с курсором вот так:
1 |
CLOSE cur1; |
Признак отсутствия данных в курсоре
В показанном примере выше, мы вообще то не знаем, вернул ли запрос в курсоре хотя бы одну строку. И выполняем операцию FETCH только для одной строки запроса, хотя их может быть больше. Нам нужен сигнал об окончании данных в курсоре. В MySQL для этого используют обработку исключительных ситуаций — конструкцию
1 |
DECLARE .. HANDLER FOR ... { } |
В нашем случае нужно продолжить исполнение (CONTINUE) при возникновении ситуации «нет данных» (NOT FOUND).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
//объявим дополнительно переменную-флажок //этот флаг будет хранить сигнал об окончании данных в курсоре DECLARE done INT DEFAULT FALSE; DECLARE a, b INT; DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1; //описываем как действовать во время исключения DECLARE CONTINUE HANDLER FOR NOT FOUND //а именно : установим флаг SET done = TRUE; //если нужно выполнить несколько команд - используйте операторные скобки //BEGIN ... END; //инициализация OPEN cur1; //цикл чтения курсора read_loop: LOOP FETCH cur1 INTO a, b; //проверка флага IF done THEN LEAVE read_loop; END IF; //обработка данных ... END LOOP; //завершаем работу с курсором CLOSE cur1; |
Думаю, этой информации достаточно, чтобы начать использовать курсоры. Есть вопросы — пишите :)