Шаг 53 - PL/SQL - КУРСОР - идем дальше

В прошлый раз мы с вами выполнили первую часть правил работы с курсором, а именно первый пункт (Объявление курсора и структуры данных, в которую, будут помещены найденные строки.)

Собственно определение структуры данных в которую, будут помещены найденные строки мы пока опустим, к ней мы еще вернемся, а пока поговорим о втором пункте (Открытие курсора).

Курсор открывается с помощью оператора OPEN. Его синтаксис следующий:

------ OPEN - имя курсора(передаваемые параметры) ---------

Давайте, определим вот такой курсор, следующим образом:

DECLARE

	v_Office OFFICES.OFFICE%TYPE;
	
	-- определяем курсор
	CURSOR get_offices IS
		SELECT * FROM OFFICES
		WHERE OFFICE = v_Office;		   

BEGIN
	-- присваиваем значение
	v_Office := 11;
	
	OPEN get_offices;	-- открываем курсор

	-- меняем значение
	v_Office := 12;

END;
/

Здесь я определил простой не параметризированный курсор, который тем не менее, получает условие через объявленную переменную, скажу сразу это не очень хороший стиль работы, но пока пусть будет так. Что же происходит когда курсор открывается? А вот, что:

  1. Анализируется значение переменных привязки.
  2. На основе значений переменных привязки определяется активный набор.
  3. Указатель активного набора устанавливается на первую строку.

Вот таким образом происходит открытие курсора. Переменные привязки анализируются только во время открытия курсора, а у нас переменная v_Office перед открытием курсора равна 11. Соответственно результирующий набор отвечает данному условию. Дальнейшее изменение переменной v_Office с 11 на 12, уже не влияет на активный набор запроса. Такой алгоритм открытия называется согласованностью чтения (read - consistency). Он разработан специально для обеспечения целостности базы данных. Чтобы получить, новый набор нужно закрыть курсор, а затем снова его открыть, вот так:

.
.
.
	OPEN get_offices;	-- открываем курсор

	CLOSE get_offices;	
	
	-- меняем значение
	v_Office := 12;
	
	OPEN get_offices;	-- открываем курсор

END;
/

Вот теперь курсор получил данные соответствующие новому значению переменной v_Office! А, можно сделать и так:

.
.
.
	OPEN get_offices;	-- открываем курсор

	-- меняем значение значение
	v_Office := 12;
	
	OPEN get_offices;	-- открываем курсор

END;
/

Так как повторное открытие курсора приводит к неявному вызову оператора CLOSE, то результат будет такой же, но использовать CLOSE, по моему мнению, более правильно, так как код более читаем и это является хорошим стилем программирования. Кроме того, совершенно допустимо открытие одновременно нескольких курсоров. Параметризованные курсоры открываются точно так же, но лишь с той разницей, что им передается заранее определенный параметр. Перепишем наш предыдущий курсор, как параметризованный, что так же является более правильным стилем программирования, вследствие того, что курсор с условием WHERE в части SELECT должен принимать условие отбора как параметр, а не как "размытую" переменную! :) Запишем:

DECLARE

	-- определяем переменную отбора
	v_Office OFFICES.OFFICE%TYPE;
	
	-- определяем параметризованный курсор
	CURSOR get_offices(v_Off OFFICES.office%TYPE) IS
		SELECT * FROM OFFICES
		WHERE OFFICE = v_Off;		   

BEGIN
	-- присваиваем значение
	v_Office := 11;
	
	OPEN get_offices(v_Office);	-- открываем курсор и передаем параметр отбора!
	
	-- меняем значение
	v_Office := 12;

END;
/

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

------ CLOSE - имя курсора ------------

Я уже упоминал, что хорошим стилем программирования является закрытие курсора, когда работа с ним окончена и вот почему. Закрытие курсора говорит о том, что программа закончила с ним работу и что все ресурсы, которые занимает данный курсор можно освободить. Если в вашей программе или процедуре один курсор, то если вы его не закроете, то система сама при завершении вызовет оператор CLOSE, но если у вас достаточно большой блок обработки с десятком курсоров, то их не закрытие может существенно снизить производительность вашего блока PL/SQL! После закрытия курсора, выбирать из него строки уже нельзя! Если попытаться это сделать, то получите сообщение об ошибке:

ORA-1001 Invalid Cursor
(неверный курсор)

или:

ORA-1002 Fetch out of  Sequence
(непоследовательное считывание)

ORA-1001 - так же срабатывает, если вы попытаетесь, закрыть уже закрытый курсор. Так что с определением открытием и закрытием курсора будем считать мы разобрались! Осталось, совсем не много ... может быть! :)


Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Летучий Сергей - 02.11.2003