Идем дальше по пути познания процедур. Итак, мы с вами рассмотрели тип передаваемых параметров - IN и OUT. Существует еще один тип параметров процедур, а именно как вы уже, наверное, догадываетесь это тип IN OUT - то есть при объявлении это выглядит примерно вот так:
CREATE OR REPLACE PROCEDURE MYPROC(MYPARAM IN OUT NUMBER .......
Вот с этим параметром давайте разберемся подробнее. Давайте сформулируем правила, для такого тип параметров.
IN OUT - этот вид представляет собой комбинацию видов IN и OUT. Значение фактического параметра передается в процедуру при ее вызове. Внутри процедуры формальный параметр может быть считан и в него может быть записано значение. При завершении процедуры и возврате управления в вызывающую среду, содержимое формального параметра присваивается фактическому параметру.
Теперь давайте создадим следующую процедуру примерно вот такого вида:
CREATE OR REPLACE PROCEDURE TESTINOUT(NUM IN OUT NUMBER, DT OUT VARCHAR2) IS BEGIN SELECT COMPANY INTO DT FROM customers WHERE customers.CUST_NUM = NUM; SELECT CUST_REP INTO NUM FROM customers WHERE customers.CUST_NUM = NUM; END TESTINOUT; /
Не торопитесь ее компилировать, давайте порасcуждаем. Итак, теперь NUM параметр IN OUT - как видно второй SELECT принимает его как параметр и возвращает через него значение. То есть принимает условие и вернет результат. Удобно, не так ли? Компилируем:
SQL> CREATE OR REPLACE PROCEDURE TESTINOUT(NUM IN OUT NUMBER, DT OUT VARCHAR2) 2 IS 3 4 BEGIN 5 6 SELECT COMPANY INTO DT FROM customers 7 WHERE customers.CUST_NUM = NUM; 8 9 SELECT CUST_REP INTO NUM FROM customers 10 WHERE customers.CUST_NUM = NUM; 11 12 END TESTINOUT; 13 / Процедура создана.
Вот теперь если сделать вот такой вызов:
SET SERVEROUTPUT ON DECLARE FRDT VARCHAR2(100); FRNM NUMBER := 2103; BEGIN TESTINOUT(FRNM, FRDT); DBMS_OUTPUT.enable; DBMS_OUTPUT.put_line('CUSTOMER '||FRDT||' CUST_REP '||TO_CHAR(FRNM)); END; /
Получаем:
SQL> SET SERVEROUTPUT ON SQL> SQL> DECLARE 2 3 FRDT VARCHAR2(100); 4 FRNM NUMBER := 2103; 5 6 BEGIN 7 8 TESTINOUT(FRNM, FRDT); 9 10 DBMS_OUTPUT.enable; 11 DBMS_OUTPUT.put_line('CUSTOMER '||FRDT||' CUST_REP '||TO_CHAR(FRNM)); 12 13 END; 14 / CUSTOMER Крупное предприятие CUST_REP 105 Процедура PL/SQL успешно завершена.
Не трудно заметить, что первое значение фактического параметра FRNM равно 2103, а вот вернул он значение 105 - т.е. один параметр выполнил двойную работу. Вполне не плохо. К слову, если вы попытаетесь сделать что-то вроде:
SET SERVEROUTPUT ON DECLARE FRDT VARCHAR2(100); BEGIN TESTINOUT(2103, FRDT); END; /
То получите в ответ следующее:
DECLARE FRDT VARCHAR2(100); BEGIN TESTINOUT(2103, FRDT); END; ORA-06550: Строка 7, столбец 12: PLS-00363: выражение '2103' не м.б. использовано как адресат назначения ORA-06550: Строка 7, столбец 2: PL/SQL: Statement ignored SQL>
В литерале 2103 нельзя сохранить возвращаемый результат, так как литерал не хранится в памяти после использования. Ну, что я думаю и так очевидно. Надеюсь, с данным типом параметра теперь вам все стало ясно! :)
Давайте теперь остановимся на понятии тела (body) процедуры. Тело процедуры содержит собственно исполняемый код и располагается между ключевыми словами BEGIN и EXCEPTION. Далее идет блок EXCEPTION и END, в котором располагается собственно обработчик исключительной ситуации. Раздел объявлений располагается между операторами CREATE и IS или AS (вот и снова язык Ada!) - а выглядит это все примерно вот так:
CREATE OR REPLACE PROCEDURE [имя процедуры] IS or AS зона объявления переменных. BEGIN выполняемый раздел EXCEPTION раздел исключительных ситуаций END [имя процедуры]
Такой скелет имеет процедура и все что к ней прилагается. Запомните это получше! :)