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 PANY%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 PANY%TYPE)
4 IS
5
6 BEGIN
7
8 I_PAR := 15.6;
9 II_PAR := 'POIUYTREWQLKJHGFDSA';
10
11 END PTEST;
12 /
Процедура создана.
Ошибок нет! Значит, все прошло успешно! Как работать с параметрами это дело вкуса, а на него, как говорится, товарищей совсем не бывает! Вот пока можете все это переварить, а я пойду попью чаю! :)
Шаг 92 - PL/SQL - Процедуры и параметры еще немного
Что ж давайте покончим с этими параметрами. Осталось рассмотреть тип применения параметров при передаче их в процедуру. Рассмотрим пример. Создадим процедуру следующего вида:
CREATE OR REPLACE PROCEDURE TEST_POZ(
PR_A IN NUMBER,
PR_B IN NUMBER,
PR_C IN VARCHAR2,
PR_D IN VARCHAR2
)
IS
BEGIN
NULL;
END TEST_POZ;
/
Ничего особенного она проделывать не будет, но зато с явным энтузиазмом будет принимать аж четыре параметра! Компилируем:
SQL> CREATE OR REPLACE PROCEDURE TEST_POZ(
2 PR_A IN NUMBER,
3 PR_B IN NUMBER,
4 PR_C IN VARCHAR2,
5 PR_D IN VARCHAR2
6 )
7 IS
8
9 BEGIN
10
11 NULL;
12
13 END TEST_POZ;
14 /
Процедура создана.
Все прошло успешно, вот и славно! А вот теперь запишем такой анонимный блок:
SET SERVEROUTPUT ON
DECLARE
PR_1 NUMBER;
PR_2 NUMBER;
PR_3 VARCHAR2(100);
PR_4 VARCHAR2(100);
BEGIN
TEST_POZ(PR_1, PR_2, PR_3, PR_4);
END;
/
Запускаем и получаем:
SQL> SET SERVEROUTPUT ON
SQL>
SQL> DECLARE
2
3 PR_1 NUMBER;
4 PR_2 NUMBER;
5 PR_3 VARCHAR2(100);
6 PR_4 VARCHAR2(100);
7
8 BEGIN
9
10 TEST_POZ(PR_1, PR_2, PR_3, PR_4);
11
12 END;
13 /
Процедура PL/SQL успешно завершена.
Смотрите, мы объявили четыре параметра и передали их нашей функции, в данном конкретном случае мы применили так называемое - "позиционное представление" (positional notation)! Такой тип передачи параметров применяется во всех языках программирования, например в таком как C и C++! Я сразу рекомендую вам пользоваться именно таким способом передачи! Хотя это еще далеко не все!
Запишем следующий анонимный блок:
SET SERVEROUTPUT ON
DECLARE
PR_1 NUMBER;
PR_2 NUMBER;
PR_3 VARCHAR2(100);
PR_4 VARCHAR2(100);
BEGIN
TEST_POZ(PR_A => PR_1, PR_B => PR_2, PR_C => PR_3, PR_D => PR_4);
END;
/
Получаем:
SQL> SET SERVEROUTPUT ON
SQL>
SQL> DECLARE
2
3 PR_1 NUMBER;
4 PR_2 NUMBER;
5 PR_3 VARCHAR2(100);
6 PR_4 VARCHAR2(100);
7
8 BEGIN
9
10 TEST_POZ(PR_A => PR_1, PR_B => PR_2, PR_C => PR_3, PR_D => PR_4);
11
12 END;
13 /
Процедура PL/SQL успешно завершена.
В данном случае я использовал - "именное представление" (named notation), которое PL/SQL унаследовал от языка Ada. В данном случае указываются как формальные, так и фактические параметры. Идем далее. Запишем следующий анонимный блок:
SET SERVEROUTPUT ON
DECLARE
PR_1 NUMBER;
PR_2 NUMBER;
PR_3 VARCHAR2(100);
PR_4 VARCHAR2(100);
BEGIN
TEST_POZ(PR_B => PR_2, PR_C => PR_3, PR_D => PR_4, PR_A => PR_1);
END;
/
Получаем:
SQL> SET SERVEROUTPUT ON
SQL>
SQL> DECLARE
2
3 PR_1 NUMBER;
4 PR_2 NUMBER;
5 PR_3 VARCHAR2(100);
6 PR_4 VARCHAR2(100);
7
8 BEGIN
9
10 TEST_POZ(PR_B => PR_2, PR_C => PR_3, PR_D => PR_4, PR_A => PR_1);
11
12 END;
13 /
Процедура PL/SQL успешно завершена.
В этом примере хорошо видно, что именное представление позволяет изменить порядок следования параметров и вызывать их, так как вам того хотелось бы. Хотя может это не всегда оправдано! :) Далее запишем следующий анонимный блок:
SET SERVEROUTPUT ON
DECLARE
PR_1 NUMBER;
PR_2 NUMBER;
PR_3 VARCHAR2(100);
PR_4 VARCHAR2(100);
BEGIN
TEST_POZ(PR_1, PR_2, PR_C => PR_3, PR_D => PR_4);
END;
/
SQL> SET SERVEROUTPUT ON
SQL>
SQL> DECLARE
2
3 PR_1 NUMBER;
4 PR_2 NUMBER;
5 PR_3 VARCHAR2(100);
6 PR_4 VARCHAR2(100);
7
8 BEGIN
9
10 TEST_POZ(PR_1, PR_2, PR_C => PR_3, PR_D => PR_4);
11
12 END;
13 /
Процедура PL/SQL успешно завершена.
Здесь хорошо видно, что позиционное и именное представление можно комбинировать, и использовать совместно. Хотя я думаю, что так легче запутать код, чтобы потом никто нифига не понял! :) Хотя это все оставляется на усмотрение программиста и стиль написания кода! Так же смею заметить, что - чем больше параметров в процедуре, тем сложнее ее вызывать и тем труднее убеждаться в наличии всех требуемых параметров. Если необходимо передать в процедуру или получить из нее достаточно большое число параметров, то рекомендуется определить тип записи, полями которой будут эти параметры. Затем можно использовать единственный параметр имеющий тип записи. В PL/SQL - так же не установлено явное ограничение на количество передаваемых в процедуру параметров.
Значение параметров по умолчанию...
Дело в том, что как и все переменные формальные параметры процедуры могут иметь значения по умолчанию. В таком случае значение параметру, имеющему такое определение можно не передавать. Если же фактический параметр все-таки передан, то принимается именно его значение. Итак, значение по умолчанию указывается вот так:
------------ имя_парметра [вид] {:= | DEFAULT} исходное_значение ------------
Давайте перепишем нашу первую процедуру с параметрами по умолчанию:
CREATE OR REPLACE PROCEDURE TEST_POZ(
PR_A IN NUMBER,
PR_B IN NUMBER,
PR_C IN VARCHAR2 := 'HELLO',
PR_D IN VARCHAR2 DEFAULT 'WORLD!!!')
IS
BEGIN
NULL;
END TEST_POZ;
/
Получаем:
SQL> CREATE OR REPLACE PROCEDURE TEST_POZ(
2 PR_A IN NUMBER,
3 PR_B IN NUMBER,
4 PR_C IN VARCHAR2 := 'HELLO',
5 PR_D IN VARCHAR2 DEFAULT 'WORLD!!!')
6 IS
7
8 BEGIN
9
10 NULL;
11
12 END TEST_POZ;
13 /
Процедура создана.
К слову, используйте параметры по умолчанию в конце списка всех параметров процедуры, при этом будет возможность использовать как именное, так и позиционное представление. Вот и все с параметрами процедур, теперь вам стало понятнее как все это работает в PL/SQL! Пробуйте!
Шаг 93 - PL/SQL - Функции
Вот теперь, наконец, давайте рассмотрим такое понятие как функции PL/SQL. Раньше в шагах мы с вами рассмотрели так называемые встроенные функции PL/SQL. А сейчас мы попробуем сами научится писать то, что называется функциями. По своей сути функция это то же, что и процедура, она может принимать параметры по всем тем же правилам, что и процедуры, и кроме всего она может возвращать значения! Но не применением OUT типа передаваемого параметра, а сама по себе. То есть функция, принимает параметры и возвращает одно(!), значение! В принципе в функции можно применять параметры с типом OUT - но это очень плохая идея! Такой метод я использовать не рекомендую! Определение функции таково:
-------------- CREATE [OR REPLACE] FUNCTION - имя_функции ------------------------------------ (аргумент [IN] [OUT] [IN OUT] тип, ..... ) AS [IS] ---------------------------- тело процедуры ---------------------------------------------------------------- RETURN (возвращаемое_значение) ----------------------------------
Кое-что вам уже знакомо, за исключением того, что присутствует оператор RETURN. Посредством этого оператора функция возвращает значение. Функция, как правило, вызывается внутри какого-либо определения, т. к. вызывать функцию как оператор нет смысла. Но как вы дальше убедитесь, с помощью функция можно делать очень полезные вещи. Итак, давайте напишем функцию преобразования BOOLEAN типа в тип VARCHAR2 - это самая простая задачка во всех учебниках. Итак:
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 |


