›  ›  ›  › Цикл FOR с курсором в PL/SQL Oracle

Цикл FOR с курсором в PL/SQL Oracle

Курсорная форма цикла FOR связывается с явно заданным курсором (а по сути, определяется им) или инструкцией SELECT, заданной непосредственно в границах цикла. Используйте эту форму только в том случае, если вам нужно извлечь и обработать все записи курсора (впрочем, при работе с курсорами это приходится делать довольно часто).

Цикл FOR с курсором — одна из замечательных возможностей PL/SQL, обеспечивающая тесную и эффективную интеграцию процедурных конструкций с мощью языка доступа к базам данных SQL. Его применение заметно сокращает объем кода, необходимого для выборки данных из курсора, а также уменьшает вероятность возникновения ошибок при циклической обработке данных — ведь именно циклы являются одним из основных источников ошибок в программах.

Синтаксис цикла FOR с курсором

FOR запись IN { имя_курсора | (команда_SELECT) }
LOOP
   исполняемые команды
END LOOP;

Здесь запись — неявно объявленная запись с атрибутом %ROWTYPE для курсора имя_курсора.

Не объявляйте явно запись с таким же именем, как у индексной записи цикла. В этом нет необходимости, поскольку запись объявляется автоматически, к тому же это может привести к логическим ошибкам.

В цикле FOR можно также задать не курсор, а непосредственно SQL-инструкцию SELECT, как показано в следующем примере:

FOR book_rec IN (SELECT * FROM books)
LOOP
   show_usage (book_rec);
END LOOP;

Не рекомендуется использовать эту форму, поскольку встраивание инструкций SELECT в код затрудняет его сопровождение и отладку.

Свойства цикла FOR с использованием курсора

Свойство Описание
Условие завершения цикла Выборка всех записей курсора. Цикл можно завершить и командой EXIT, но поступать так не рекомендуется
Когда проверяется условие завершения цикла После каждого выполнения тела цикла компилятор PL/SQL осуществляет выборку очередной записи. Если значение атрибута курсора %NOTFOUND% оказывается равным TRUE, цикл завершается. Если курсор не возвратит ни одной строки, тело цикла никогда не будет выполнено
В каких случаях используется данный цикл При необходимости выбрать и обработать каждую запись курсора

Примеры цикла FOR с курсором

Допустим, необходимо обновить счета владельцев всех животных, живущих в специальном отеле. Следующий пример включает анонимный блок, в котором для выбора номера комнаты и идентификатора животного используется курсор occupancy_cur. Процедура update_bill вносит все изменения в счет:

DECLARE
   CURSOR occupancy_cur IS
      SELECT pet_id, room_number
        FROM occupancy WHERE occupied_dt = TRUNC (SYSDATE);
   occupancy_rec occupancy_cur%ROWTYPE;
BEGIN
   OPEN occupancy_cur;
   LOOP
      FETCH occupancy_cur INTO occupancy_rec;
      EXIT WHEN occupancy_cur%NOTFOUND;
      update_bill
          (occupancy_rec.pet_id, occupancy_rec.room_number);
    END LOOP;
    CLOSE occupancy_cur;
END;

Этот код последовательно и явно выполняет все необходимые действия: мы определяем курсор (строка 2), явно объявляем запись для этого курсора (строка 5), открываем курсор (строка 7), начинаем бесконечный цикл (строка 8), производим выборку записи из курсора (строка 9), проверяем условие выхода из цикла (конец данных) по атрибуту %NOTFOUND курсора (строка 10) и, наконец, выполняем обновление (строка 11). После этого программист должен закрыть курсор (строка 14).

Вот что получится, если переписать тот же код с использованием цикла FOR с курсором:

DECLARE
   CURSOR occupancy_cur IS
      SELECT pet_id, room_number
        FROM occupancy WHERE occupied_dt = TRUNC (SYSDATE);
BEGIN
   FOR occupancy_rec IN occupancy_cur
   LOOP
      update_bill (occupancy_rec.pet_id, occupancy_rec.room_number);
   END LOOP;
END;

Как все просто и понятно! Исчезло объявление записи. Исчезли команды OPEN, FETCH и CLOSE. Больше не нужно проверять атрибут %NOTFOUND. Нет никаких сложностей с организацией выборки данных. По сути, вы говорите PL/SQL: «Мне нужна каждая строка таблицы, и я хочу, чтобы она была помещена в запись, соответствующую курсору». И PL/SQL делает то, что вы хотите, как это должен делать любой современный язык программирования.

Курсору в цикле FOR, как и любому другому курсору, можно передавать параметры. Если какой-либо из столбцов списка SELECT определяется выражением, обязательно определите для него псевдоним. Для обращения к конкретному значению в записи курсора в пределах цикла необходимо использовать «точечный» синтаксис (имя_записи.имя_столбца — например, occupancy_rec.room_number), так что без псевдонима к столбцу-выражению обратиться не удастся.

Метки: , , .

Записи по теме

Добавить комментарий

Ваш адрес email не будет опубликован.