Добавить в корзинуПозвонить
Найти в Дзене
Oracle Developer

Курсоры в Oracle

Друзья, всем привет! 👋 С вами Костя Андронов. Один из популярных вопросов на собеседовании по Oracle: Что такое курсор? Курсор — это указатель на область памяти, в которой Oracle хранит результат SQL-запроса. Когда выполняется SELECT или DML, БД складывает строки в эту область, а курсор позволяет извлекать их в вызывающую среду. В Oracle курсоры бывают двух видов: неявные и явные 🧩 Неявный курсор Создаётся автоматически для любого SQL-запроса внутри PL/SQL-блока. Мы его не объявляем и не закрываем — Oracle делает всё сам. Строго говоря, неявный курсор - это вообще любая SQL-команда: truncate, create, commit, select... begin delete from dept_temp where department_id = 10; if sql%found then dbms_output.put_line('Удалено строк: ' || sql%rowcount); end if; end; 🧩 Явный курсор Объявляем сами, сами открываем, читаем построчно и закрываем. Даёт полный контроль над выборкой и умеет принимать параметры. declare cursor c_emp (p_dept number) is select department_id, department_name

Курсоры в Oracle

Друзья, всем привет! 👋

С вами Костя Андронов.

Один из популярных вопросов на собеседовании по Oracle:

Что такое курсор?

Курсор — это указатель на область памяти, в которой Oracle хранит результат SQL-запроса. Когда выполняется SELECT или DML, БД складывает строки в эту область, а курсор позволяет извлекать их в вызывающую среду.

В Oracle курсоры бывают двух видов: неявные и явные

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

Создаётся автоматически для любого SQL-запроса внутри PL/SQL-блока. Мы его не объявляем и не закрываем — Oracle делает всё сам.

Строго говоря, неявный курсор - это вообще любая SQL-команда: truncate, create, commit, select...

begin

delete

from dept_temp

where department_id = 10;

if sql%found then

dbms_output.put_line('Удалено строк: ' || sql%rowcount);

end if;

end;

🧩 Явный курсор

Объявляем сами, сами открываем, читаем построчно и закрываем. Даёт полный контроль над выборкой и умеет принимать параметры.

declare

cursor c_emp (p_dept number) is

select department_id,

department_name

from dept_temp

where department_id = p_dept;

v_rec c_emp%rowtype;

begin

open c_emp(10);

loop

fetch c_emp into v_rec;

exit when c_emp%notfound;

dbms_output.put_line(v_rec.department_name);

end loop;

close c_emp;

end;

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

❓ В чем сложность при работе с явными курсорами?

Если возникнет исключение между open и close (например, в fetch или в dbms_output), управление сразу уйдёт за пределы блока (или в exception-секцию, если она есть), и close c_emp; не выполнится.

Курсор останется открытым 😱

Почему это плохо:

🔸 Курсор занимает слот в open_cursors сессии, а они ограничены

🔸 Если такой блок вызывается в цикле или в процедуре, которая вызывается часто, рано или поздно можно поймать ORA-01000: maximum open cursors exceeded

🔸 В анонимном блоке верхнего уровня, после окончания вызова, Oracle сам подчистит сессионные ресурсы, но полагаться на это — плохая практика.

⚠️ Как с этим бороться?

1️⃣ Перехватить исключение в exception блоке

...

exception

when others then

if c_emp%isopen then

close c_emp;

end if;

raise;

end;

2️⃣ Использовать цикл FOR. Oracle сам объявит переменную типа %rowtype, откроет и закроет курсор (даже при исключении), будет извлекать строки по 1 на каждой итерации обязательного цикла:

begin

for rec in (select department_name

from dept_temp

where department_id = 10)

loop

dbms_output.put_line(rec.department_name);

end loop;

end;

📌 Зачем нужны курсоры?

✅ Неявный — когда достаточно выполнить запрос и узнать, что вышло: сколько строк затронуто, был ли результат

✅ Явный — когда нужны параметры, контроль над FETCH, обработка нескольких выборок одновременно или передача курсора между процедурами через REF CURSOR.

❤️ Если тема зашла — cтавьте 👍🏻, разберём, есть ли разница в производительности между явным и неявным курсором

С вами был Костя Андронов. Всем продуктивного дня! 🚀

#oracle #plsql #курсоры #Konstantin_Andronov

Канал Oracle Developer | Чатик 💬

Мини-курс Оптимизация: Быстрый старт 🚀

📱 YouTube 📱 ВКонтакте 📱 LinkedIn 📱Threads

RUTUBE