Шаг 91 - PL/SQL - Процедуры и параметры III

Думаю, что вам уже кажется, что с процедурами и их параметрами мы разобрались, а вот и нет! Есть еще кое-что. Думаю, кто-то из вас заметил, что при написании формального параметра процедуры, например, определяя ее как VARCHAR2 или NUMBER я никогда не делал вот так:

CREATE OR REPLACE PROCEDURE some_proc(NUM IN OUT NUMBER(3,2), DT OUT VARCHAR2(100))

И вот почему. Накладывать ограничения на формальные параметры функций в PL/SQL - ЗАПРЕЩЕНО! Например, вот такой пример, приведет к ошибке компиляции:

CREATE OR REPLACE PROCEDURE TESTINOUT(NUM IN OUT NUMBER(3,2), DT OUT VARCHAR2(100))
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;
/

В результате получите:

SQL> CREATE OR REPLACE PROCEDURE TESTINOUT(NUM IN OUT NUMBER(3,2), DT OUT VARCHAR2(100))
  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  /

Предупреждение: Процедура создана с ошибками компиляции.

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

CREATE OR REPLACE PROCEDURE PTEST(I_PAR IN OUT NUMBER, II_PAR IN OUT VARCHAR2)
IS

BEGIN

	I_PAR := 15.6;
	II_PAR := 'POIUYTREWQLKJHGFDSA';

END PTEST;
/

Компилируем:

SQL> CREATE OR REPLACE PROCEDURE PTEST(I_PAR IN OUT NUMBER, II_PAR IN OUT VARCHAR2)
  2  IS
  3  
  4  BEGIN
  5  
  6   I_PAR := 15.6;
  7   II_PAR := 'POIUYTREWQLKJHGFDSA';
  8  
  9  END PTEST;
 10  /

Процедура создана.

Вот теперь I_PAR и II_PAR получили неявное ограничение посредством объявлений:

I_PAR := 15.6;
II_PAR := 'POIUYTREWQLKJHGFDSA';

т.е. получилось, что то вроде:

CREATE OR REPLACE PROCEDURE PTEST(I_PAR IN OUT NUMBER(3.4), II_PAR IN OUT VARCHAR2(19))

Теперь, если произвести вот такой вызов:

DECLARE 

V_STR VARCHAR2(10);
V_NUM NUMBER(3,4); 

BEGIN

	PTEST(V_NUM, V_STR);

END;
/

Получаем, что-то довольно странное:

SQL> DECLARE
  2  
  3  V_STR VARCHAR2(10);
  4  V_NUM NUMBER(3,4);
  5  
  6  BEGIN
  7  
  8   PTEST(V_NUM, V_STR);
  9  
 10  END;
 11  /
DECLARE
*
ошибка в строке 1:
ORA-06502: PL/SQL: : буфер символьных строк слишком маленький ошибка числа или значения 
ORA-06512: на  "MILLER.PTEST", line 7 
ORA-06512: на  line 8 

SQL>

Не сразу ясно, что происходит, так? А все очень просто, V_STR VARCHAR2(10) переопределила ограничение переменной II_PAR при ее явном вызове и запись строки длинной 19 символов в переменную всего в 10 символов привело к ошибке! Очень важно это понимать, иначе в дальнейшем вы запутаетесь совсем! Здесь ошибку вызвала сама вызывающая программа, а не код процедуры, как может показаться! Так вот во избежание ошибок, подобных ORA-06502 при создании процедур документируйте все ограничения налагаемые на фактические параметры - вносите в хранимые процедуры комментарии, а так же кроме описания каждого параметра записывайте функции выполняемые самой процедурой! Вот тогда я думаю, у вас все получится!

Так же единственным способом наложения ограничения на формальный параметр функции является использование оператора %TYPE. Мы с вами о нем говорили. В свете этого можно переписать нашу функцию пример - скажем, вот так:

CREATE OR REPLACE PROCEDURE PTEST(
                      I_PAR IN OUT CUSTOMERS.CUST_NUM%TYPE, 
                      II_PAR IN OUT CUSTOMERS.COMPANY%TYPE)
IS

BEGIN

	I_PAR := 15.6;
	II_PAR := 'POIUYTREWQLKJHGFDSA';

END PTEST;
/

Такой способ удобен тем, что при изменении полей таблицы автоматом меняются параметры процедур, что облегчает сопровождение кода хранимых процедур, не нужно менять все параметры связанные с данным полем! Получаем:

SQL> CREATE OR REPLACE PROCEDURE PTEST(
  2  	I_PAR IN OUT CUSTOMERS.CUST_NUM%TYPE,
  3  	II_PAR IN OUT CUSTOMERS.COMPANY%TYPE)
  4  IS
  5  
  6  BEGIN
  7  
  8  	I_PAR := 15.6;
  9  	II_PAR := 'POIUYTREWQLKJHGFDSA';
 10  
 11  END PTEST;
 12  /

Процедура создана.

Ошибок нет! Значит, все прошло успешно! Как работать с параметрами это дело вкуса, а на него, как говорится, товарищей совсем не бывает! Вот пока можете все это переварить, а я пойду попью чаю! :)


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