Раньше мы с вами рассматривали оператор 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 успешно завершена.
Что собственно и требовалось доказать. Вот так работают курсоры с параметрами и без таковых. Надеюсь, теперь вы научились писать курсоры, и выбирать из них данные! :)