Шаг 63 - PL/SQL - КУРСОРЫ - курсоры с параметрами

Раньше мы с вами рассматривали оператор SELECT, который получал все данные из таблиц. Но как известно, чаще вы будете использовать условие WHERE в курсорном операторе SELECT. И в дальнейшем вам будет необходимо определять условия выборки. Как это сделать наиболее правильно, самый простой способ вот так:

-- Пишем курсор с условием
CURSOR get_sls IS
	SELECT * FROM SALESREPS
	WHERE AGE = 37;

Замечательно, а если нужно другое значение отличное от 37? Что тогда? Напрашивается вывод о том, что в этом случае необходим курсор с параметрами или "параметризованный курсор"! Он определяется вот так:

CURSOR get_sls(INAGE NUMBER) IS
	SELECT * FROM SALESREPS
	WHERE AGE = INAGE;

Но еще более правильно, будет сделать вот так:

CURSOR get_sls(INAGE SALESREPS.AGE%TYPE) IS
	SELECT * FROM SALESREPS
	WHERE AGE = INAGE;

Применив оператор TYPE мы сделали код более мобильным, так как если тип поля изменится, то не нужно будет лопатить весь код в поисках ошибки! Это так же считается наиболее правильным стилем программирования! :) И теперь при открытии такого курсора, его оператор OPEN будет принимать передаваемый параметр вот так:

OPEN get_sls(37); 

Подытожим наши заключения следующим блоком:

SET SERVEROUTPUT ON

DECLARE
	
	CURSOR get_sls(INAGE SALESREPS.AGE%TYPE) IS
		SELECT * FROM SALESREPS
		WHERE AGE = INAGE;

	in_sls get_sls%ROWTYPE;

BEGIN
	
	DBMS_OUTPUT.enable;
	
	OPEN get_sls(37);
		
	FETCH get_sls INTO in_sls;
	
	LOOP 

		DBMS_OUTPUT.put_line('Record is: '||in_sls.NAME||' '||in_sls.TITLE||' '||in_sls.HIRE_DATE);

		FETCH get_sls INTO in_sls;
		EXIT WHEN get_sls%NOTFOUND;

	END LOOP;
			
	CLOSE get_sls; 
	
END;
/

После запуска получаем:

SQL> SET SERVEROUTPUT ON
SQL> DECLARE
  2  
  3  	CURSOR get_sls(INAGE SALESREPS.AGE%TYPE) IS
  4  		SELECT * FROM SALESREPS
  5  		WHERE AGE = INAGE;
  6  
  7  	in_sls get_sls%ROWTYPE;
  8  
  9  BEGIN
 10  
 11  	DBMS_OUTPUT.enable;
 12  
 13  	OPEN get_sls(37);
 14  
 15  	FETCH get_sls INTO in_sls;
 16  
 17  	LOOP
 18  
 19  		DBMS_OUTPUT.put_line('Record is: '||in_sls.NAME||' '||in_sls.TITLE||' '||in_sls.HIRE_DATE);
 20  
 21  		FETCH get_sls INTO in_sls;
 22  		EXIT WHEN get_sls%NOTFOUND;
 23  
 24  	END LOOP;
 25  
 26  	CLOSE get_sls;
 27  
 28  END;
 29  /
Record is: Вася Пупкин Рапорт продажа 12.02.88
Record is: Максим Галкин Продано все 12.10.89

Процедура PL/SQL успешно завершена.

Вот так отработал наш с вами первый параметризованный курсор, надеюсь, все понятно, если нет - спрашивайте! Для закрепления, давайте запишем тот же курсор, с циклом FOR:

SET SERVEROUTPUT ON

DECLARE
	
	CURSOR get_sls(INAGE SALESREPS.AGE%TYPE) IS
		SELECT * FROM SALESREPS
		WHERE AGE = INAGE;

BEGIN
	
	DBMS_OUTPUT.enable;
	
	FOR in_sls IN get_sls(37) LOOP
	
		DBMS_OUTPUT.put_line('Record is: '||in_sls.NAME||' '||in_sls.TITLE||' '||in_sls.HIRE_DATE);

	END LOOP;

END;
/

Получаем:

SQL> DECLARE
  2  
  3  	CURSOR get_sls(INAGE SALESREPS.AGE%TYPE) IS
  4  		SELECT * FROM SALESREPS
  5  		WHERE AGE = INAGE;
  6  
  7  BEGIN
  8  
  9  	DBMS_OUTPUT.enable;
 10  
 11  	FOR in_sls IN get_sls(37) LOOP
 12  
 13  		DBMS_OUTPUT.put_line('Record is: '||in_sls.NAME||' '||in_sls.TITLE||' '||in_sls.HIRE_DATE);
 14  
 15  	END LOOP;
 16  
 17  END;
 18  /
Record is: Вася Пупкин Рапорт продажа 12.02.88
Record is: Максим Галкин Продано все 12.10.89

Процедура PL/SQL успешно завершена.

Параметров у курсора может быть несколько, например вот так:

SET SERVEROUTPUT ON

DECLARE
	
	CURSOR get_sls(INMG SALESREPS.MANAGER%TYPE, INSL SALESREPS.SALES%TYPE) IS
		SELECT * FROM SALESREPS
		WHERE MANAGER = INMG AND SALES > INSL;

BEGIN
	
	DBMS_OUTPUT.enable;
	
	FOR in_sls IN get_sls(104, 300) LOOP
	
		DBMS_OUTPUT.put_line('Record is: '||in_sls.NAME||' '||in_sls.TITLE||' '||TO_CHAR(in_sls.HIRE_DATE,'DD-MM-YYYY')||
		' '||TO_CHAR(in_sls.SALES));

	END LOOP;

END;
/

Получаем после запуска:

SQL> DECLARE
  2  
  3  	CURSOR get_sls(INMG SALESREPS.MANAGER%TYPE, INSL SALESREPS.SALES%TYPE) IS
  4  		SELECT * FROM SALESREPS
  5  		WHERE MANAGER = INMG AND SALES > INSL;
  6  
  7  BEGIN
  8  
  9  	DBMS_OUTPUT.enable;
 10  
 11  	FOR in_sls IN get_sls(104, 300) LOOP
 12  
 13  		DBMS_OUTPUT.put_line('Record is: '||in_sls.NAME||' '||in_sls.TITLE||' '||TO_CHAR(in_sls.HIRE_DATE,'DD-MM-YYYY')||
 14  		' '||TO_CHAR(in_sls.SALES));
 15  
 16  	END LOOP;
 17  
 18  END;
 19  /
Record is: Вася Пупкин Рапорт продажа 12-02-1988 367,911
Record is: Игорь Николаев Рапорт продажа 20-10-1986 305,673

Процедура PL/SQL успешно завершена.

Что собственно и требовалось доказать. Вот так работают курсоры с параметрами и без таковых. Надеюсь, теперь вы научились писать курсоры, и выбирать из них данные! :)


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