Думаю, что вам уже кажется, что с процедурами и их параметрами мы разобрались, а вот и нет! Есть еще кое-что. Думаю, кто-то из вас заметил, что при написании формального параметра процедуры, например, определяя ее как 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 / Процедура создана.
Ошибок нет! Значит, все прошло успешно! Как работать с параметрами это дело вкуса, а на него, как говорится, товарищей совсем не бывает! Вот пока можете все это переварить, а я пойду попью чаю! :)