Oracle Курсор PL/SQL: неявный, явный, цикл For с примером

⚡ Умное резюме

Курсоры в Oracle В PL/SQL используются указатели на контекстную область, содержащую строки, возвращаемые SQL-запросом. Существует два типа курсоров: неявные курсоры, создаваемые автоматически для операций DML, и явные курсоры, объявляемые и управляемые программистом.

  • 📍 Область контекста: Курсор указывает на контекстную область, в которой хранится SQL-запрос и возвращаемый им активный набор.
  • ⚙️ Неявный курсор: Oracle Автоматически открывает неявный курсор для каждого оператора DML и однострочного запроса SELECT INTO.
  • Явный курсор: Программист объявляет, открывает, получает и закрывает конкретный курсор для полного управления.
  • 🔎 Атрибуты курсора: Значения %FOUND, %NOTFOUND, %ISOPEN и %ROWCOUNT отображают статус последней операции.
  • 🔁 Цикл FOR курсора: Цикл FOR неявно открывает, извлекает и закрывает курсор, не требуя никаких действий вручную.
  • 🤖 Помощь ИИ: Искусственный интеллект, например, в GitHub Copilot, позволяет отслеживать циклы курсоров в черновиках и помечать незакрытые курсоры.

Oracle PL/SQL Курсор Неявный Явный и Цикл FOR

Что такое КУРСОР в PL/SQL?

Курсор — это указатель на контекстную область. Oracle создает контекстную область для обработки SQL заявление, и в этом разделе содержится вся информация о заявлении.

PL/SQL Это позволяет программисту управлять контекстной областью с помощью курсора. Курсор содержит строки, возвращаемые SQL-запросом, а набор строк, которые он содержит, называется активным набором. Эти курсоры также могут быть именованы, чтобы на них можно было ссылаться из другого места в коде.

Курсор бывает двух типов:

  • Неявный курсор
  • Явный курсор

Неявный курсор

Всякий раз, когда любой Операция DML При возникновении операции в базе данных создается неявный курсор, содержащий строки, затронутые данной операцией. Эти курсоры не могут быть именованы, и, следовательно, ими нельзя управлять или на них нельзя ссылаться из другого места в коде. Мы можем ссылаться только на самый последний курсор через атрибуты курсора.

Явный курсор

Программистам разрешается создавать именованную контекстную область для выполнения операций DML и получения большего контроля над ней. Явный курсор должен быть определен в разделе объявления. Блок PL / SQLи он создается для оператора SELECT, который необходимо использовать в коде.

Ниже описаны шаги, необходимые для работы с явно указанными курсорами:

  • Объявление курсора: Объявление курсора просто означает создание одной именованной контекстной области для оператора SELECT, определенного в части объявления. Имя этой контекстной области совпадает с именем курсора.
  • Открытие курсора: Открытие курсора дает указание PL/SQL выделить память для этого курсора. Это подготавливает курсор к извлечению записей.
  • Получение данных из курсора: В этом процессе выполняется оператор SELECT, и полученные строки сохраняются в выделенной памяти. Теперь они называются активными наборами. Получение данных из курсора — это операция на уровне записи, что означает, что мы можем получать доступ к данным по каждой записи отдельно. Каждый оператор fetch извлекает один активный набор и хранит информацию об этой конкретной записи. Этот оператор аналогичен оператору SELECT, который извлекает запись и присваивает ее переменной в предложении INTO, но он не вызовет никаких ошибок. Исключения.
  • Закрытие курсора: После того как все записи будут получены, необходимо закрыть курсор, чтобы освободить память, выделенную для этой контекстной области.

Синтаксис

DECLARE
CURSOR <cursor_name> IS <SELECT statement>;
<cursor_variable declaration>;
BEGIN
OPEN <cursor_name>;
FETCH <cursor_name> INTO <cursor_variable>;
.
.
CLOSE <cursor_name>;
END;

В приведенном выше синтаксисе часть объявления содержит объявление курсора и переменную курсора, которой будут присвоены полученные данные. Курсор создается для оператора SELECT, указанного в объявлении курсора. В части выполнения объявленный курсор открывается, извлекаются данные и закрывается.

Атрибуты курсора

Как неявный, так и явный курсор имеют определенные доступные атрибуты. Эти атрибуты предоставляют дополнительную информацию об операциях с курсором. Ниже приведены различные атрибуты курсора и их использование.

Атрибут курсора Описание
%НАЙДЕННЫЙ Возвращает логический результат TRUE, если последняя операция получения данных успешно завершилась; в противном случае возвращает FALSE.
%НЕ НАЙДЕНО Работает в обратном порядке по отношению к %FOUND. Возвращает TRUE, если последняя операция получения данных не смогла получить ни одной записи.
%ОТКРЫТ Возвращает логическое значение TRUE, если заданный курсор уже открыт; в противном случае возвращает FALSE.
% ROWCOUNT Возвращает числовое значение, указывающее фактическое количество записей, затронутых или полученных в результате операции.

Пример явного отображения курсора: В этом примере мы рассмотрим, как объявить, открыть, получить и закрыть явный курсор. Мы спроецируем все имена сотрудников из таблицы emp с помощью курсора. Мы также будем использовать атрибут курсора, чтобы задать цикл для получения всех записей из курсора.

На скриншоте ниже показан этот пример с явным отображением курсора и его результат. Oracle.

Пример явного курсора для извлечения имен сотрудников из таблицы emp. Oracle PL/SQL

DECLARE
CURSOR guru99_det IS SELECT emp_name FROM emp;
lv_emp_name emp.emp_name%type;
BEGIN
OPEN guru99_det;
LOOP
FETCH guru99_det INTO lv_emp_name;
IF guru99_det%NOTFOUND
THEN
EXIT;
END IF;
Dbms_output.put_line('Employee Fetched:'||lv_emp_name);
END LOOP;
Dbms_output.put_line('Total rows fetched is'||guru99_det%ROWCOUNT);
CLOSE guru99_det;
END;
/

Результат

Employee Fetched:BBB
Employee Fetched:XXX
Employee Fetched:YYY
Total rows fetched is 3

Code объяснение

  • Code строка 2: Объявляем курсор guru99_det для оператора 'SELECT emp_name FROM emp'.
  • Code строка 3: Объявление переменной lv_emp_name с помощью %тип привязано к emp.emp_name.
  • Code строка 5: Открытие курсора guru99_det.
  • Code строка 6: Настройка базового цикла для получения всех записей из таблицы emp.
  • Code строка 7: Получает данные из переменной guru99_det и присваивает значение переменной lv_emp_name.
  • Code строка 8: Используя атрибут курсора %NOTFOUND, проверяется, были ли получены все записи из курсора. Если да, возвращается TRUE, и управление выходит из цикла; в противном случае управление продолжает получать данные из курсора и выводит их.
  • Code строка 10: Условие EXIT для оператора цикла.
  • Code строка 12: Распечатайте полученное имя сотрудника.
  • Code строка 14: Используйте атрибут курсора %ROWCOUNT, чтобы узнать общее количество записей, извлеченных курсором.
  • Code строка 15: После выхода из цикла курсор закрывается, и выделенная память освобождается.

Оператор циклического курсора FOR

Курсор Цикл FOR Его можно использовать для работы с курсорами. Вместо ограничения диапазона в операторе цикла FOR мы можем указать имя курсора, чтобы цикл работал от первой записи курсора до последней. Переменная курсора, открытие курсора, выборка и закрытие курсора выполняются неявно циклом FOR.

Синтаксис

DECLARE
CURSOR <cursor_name> IS <SELECT statement>;
BEGIN
FOR I IN <cursor_name>
LOOP
.
.
END LOOP;
END;

В приведенном выше синтаксисе часть объявления содержит объявление курсора. Курсор создается для оператора SELECT, указанного в объявлении курсора. В части выполнения объявленный курсор устанавливается в цикле FOR, и переменная цикла 'I' в данном случае выступает в роли переменной курсора.

Oracle Пример цикла for с использованием курсора: В этом примере мы спроецируем все имена сотрудников из таблицы emp, используя цикл FOR с курсором.

DECLARE
CURSOR guru99_det IS SELECT emp_name FROM emp;
BEGIN
FOR lv_emp_name IN guru99_det
LOOP
Dbms_output.put_line('Employee Fetched:'||lv_emp_name.emp_name);
END LOOP;
END;
/

Результат

Employee Fetched:BBB
Employee Fetched:XXX
Employee Fetched:YYY

Code объяснение

  • Code строка 2: Объявляем курсор guru99_det для оператора 'SELECT emp_name FROM emp'.
  • Code строка 4: Создание цикла FOR для курсора с переменной цикла lv_emp_name.
  • Code строка 6: Печать имени сотрудника на каждой итерации цикла.
  • Code строка 7: Выйти из цикла (КОНЕЦ ЦИКЛА).

Примечание: В цикле FOR с курсором атрибуты курсора использовать нельзя, поскольку открытие, выборка и закрытие курсора выполняются неявно самим циклом FOR.

Часто задаваемые вопросы (FAQ)

REF CURSOR (переменная курсора) — это указатель на набор результатов запроса. В отличие от статического курсора, он может открывать разные запросы во время выполнения и передавать результаты между блоками PL/SQL или клиентским программам.

Обычный курсор считывает одну строку за один цикл выборки (FETCH), что приводит к многочисленным переключениям контекста. ОПТОВЫЙ СБОР Загружает множество строк в коллекцию за один запрос, что значительно снижает накладные расходы при работе с большими наборами результатов.

Да. Объявите параметризованный курсор, например, CURSOR c(dept NUMBER) IS SELECT …, затем передайте значения в OPEN c(10). Параметры позволяют повторно использовать одно определение курсора с различными значениями фильтра.

Оператор FOR UPDATE блокирует строки, выбранные курсором, чтобы никто другой не мог их изменить. Оператор WHERE CURRENT OF обновляет или удаляет только что полученную строку, не повторяя условие WHERE.

Открытые курсоры сохраняют зарезервированную память и учитываются в лимите OPEN_CURSORS. Если оставить много открытых курсоров, в конечном итоге возникнет ошибка ORA-01000: превышено максимальное количество открытых курсоров, поэтому всегда закрывайте явно используемый курсор после его использования.

Каждый вызов FETCH переключает между механизмами PL/SQL и SQL. Тысячи таких переключений контекста в сумме дают значительный результат, поэтому один SQL-запрос на основе набора данных или вызов BULK COLLECT обычно обрабатывают одни и те же строки гораздо быстрее.

Да. Второй пилот GitHub Добавляет явные циклы OPEN, FETCH и CLOSE или циклы FOR с курсором из комментария, проверяет наличие ошибок выхода %NOTFOUND и предлагает имена атрибутов, хотя сначала следует проверить логику.

Искусственный интеллект выявляет циклы курсоров, выполняемые построчно, которые могут превратиться в SQL-запросы на основе множеств или запросы BULK COLLECT, обнаруживает незакрытые курсоры и объясняет поведение функции %attribute. Этот анализ с помощью машинного обучения повышает производительность до того, как код попадет в продакшн.

Подведем итог этой публикации следующим образом: