EXEC TESTERR;

Ответ будет таким:

SQL> EXEC TESTERR;

BEGIN TESTERR; END;

*

ошибка в строке 1:

ORA-06550: Строка 1, столбец 7:

PLS-00905: неприемлемый объект MILLER. TESTERR

ORA-06550: Строка 1, столбец 7:

PL/SQL: Statement ignored

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

.

.

7

8 K := NUM

9

10 END TESTERR;

11 /

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

И дадим такую строку:

SHOW ERRORS

Получаем:

SQL> SHOW ERRORS

Ошибки для PROCEDURE TESTERR:

LINE/COL ERROR

-------- -----------------------------------------------------------------

10/1 PLS-00103: Встретился символ "END" в то время как ожидалось одно

из следующих:

. ( * @ % & = - + ; < / > at in is mod not rem

<an exponent (**)> <> or!= or ~= >= <= <> and or like

between ||

Символ ";" заменен на "END", чтобы можно было продолжать.

Вот теперь кое, кое что стало яснее. Ошибка PLS-00103 означает наличие незавершенного оператора, команда SHOW ERRORS, считывает данные из системного представления USER_ERRORS, вот его описание:

SQL> DESC USER_ERRORS

Имя Пусто? Тип

--------- -------- ----------------------------

NAME NOT NULL VARCHAR2(30)

TYPE VARCHAR2(12)

SEQUENCE NOT NULL NUMBER

LINE NOT NULL NUMBER

POSITION NOT NULL NUMBER

TEXT NOT NULL VARCHAR2(4000)

Теперь давайте дадим вот такой запрос:

НЕ нашли? Не то? Что вы ищете?

SELECT NAME, TEXT FROM USER_ERRORS

/

Вот и содержимое:

SQL> SELECT NAME, TEXT FROM USER_ERRORS

2 /

NAME TEXT

------- -----------------------------------------------------------------------

TESTERR PLS-00103: Встретился символ "END" в то время как ожидалось одно из следующих:

. ( * @ % & = - + ; < / > at in is mod not rem

<an exponent (**)> <> or!= or ~= >= <= <> and or like

between ||

Символ ";" заменен на "END", чтобы можно было продолжать.

Вообще это дело вкуса, но лучше использовать SHOW ERRORS - так удобнее. И будет ясно видно где ошибка! Давайте удалим нашу "инвалидную" процедуру и вы сможете сами поработать над тем, что я вам излагал! Итак:

DROP PROCEDURE TESTERR

/

SQL> DROP PROCEDURE TESTERR

2 /

Процедура удалена.

Пока все, поработайте сами! :)

Шаг 95 - PL/SQL - Хранимые процедуры, объявления, зависимости

Для ясности картины давайте подведем некую черту под, классификацией хранимых и локальных (анонимных или неименованных) процедурах. Скажу сразу, старайтесь как можно больше использовать именно хранимые подпрограммы (процедуры и функции), а анонимные блоки, только в процессе создания и отладки. Вот таблица, для их сравнения:

Хранимые подпрограммы

Локальные подпрограммы

Хранятся в БД в скомпилированном p-коде, при вызове процедуру не нужно компилировать.

Компилируются фрагменты и содержащиеся в них блоки. При повторном выполнении производится новая компиляция.

Могут вызываться из любого блока запущенного на выполнение пользователем который имеет привилегии EXECUTE для данной подпрограммы.

Могут вызываться только из содержащего их блока.

Код подпрограммы хранится отдельно от вызывающего блока, по этому вызывающий блок короче и легче для понимания. Кроме того, при желании с подпрограммой и вызывающим блоком можно работать по отдельности.

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

Скомпилированный p-код можно закрепить в разделяемом пуле при помощи модульной процедуры DBMS_SHARED_POOL. KEEP. Это приводит к повышению производительности системы в целом.

Непосредственно локальные подпрограммы нельзя закреплять в разделяемом пуле.

Вот собственно кратко различия, между двумя видами программных блоков. А теперь давайте поговорим на тему, зависимости объектов БД. Дело в том, что при компиляции процедуры или функции, как и все объекты Oracle, на которые производится ссылки записываются в словарь данных. Возникает так называемая зависимость (depend) объектов друг от друга. Давайте рассмотрим это на примере. Пусть, скажем, имеется таблица TBLA, (создадим ее):

CREATE TABLE TBLA(

FIELDA VARCHAR2(100),

FIELDB NUMBER(3,5)

)

/

Получаем:

SQL> CREATE TABLE TBLA(

2 FIELDA VARCHAR2(100),

3 FIELDB NUMBER(3,5)

4 )

5 /

Таблица создана.

Предположим что, после этого вы создаете процедуру такого вида:

CREATE PROCEDURE TEST_DEPEND(PRMA IN TBLA. FIELDA%TYPE, PRMB IN TBLA. FIELDB%TYPE)

IS

BEGIN

NULL;

END TEST_DEPEND;

/

Получаем после компиляции:

SQL> CREATE PROCEDURE TEST_DEPEND(PRMA IN TBLA. FIELDA%TYPE, PRMB IN TBLA. FIELDB%TYPE)

2 IS

3

4 BEGIN

5

6 NULL;

7

8 END TEST_DEPEND;

9 /

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

Посмотрим на состояние объектов:

SELECT OBJECT_NAME, OBJECT_TYPE, STATUS

FROM USER_OBJECTS

WHERE OBJECT_NAME IN ('TBLA','TEST_DEPEND')

/

Получаем:

SQL> SELECT OBJECT_NAME, OBJECT_TYPE, STATUS

2 FROM USER_OBJECTS

3 WHERE OBJECT_NAME IN ('TBLA','TEST_DEPEND')

4 /

OBJECT_NAME OBJECT_TYPE STATUS

---------------- ------------------ -------

TEST_DEPEND PROCEDURE VALID

TBLA TABLE VALID

Все прекрасно, но это только пока. Допустим по каким-либо причинам вы изменили таблицу TBLA вот так:

ALTER TABLE TBLA ADD FIELDC NUMBER(5,7)

/

Получаем в результате:

SQL> ALTER TABLE TBLA ADD FIELDC NUMBER(5,7)

2 /

Таблица изменена.

А вот теперь, если посмотреть на состояние объектов, то мы увидим следующее:

SELECT OBJECT_NAME, OBJECT_TYPE, STATUS

FROM USER_OBJECTS

WHERE OBJECT_NAME IN ('TBLA','TEST_DEPEND')

/

Получаем:

SQL> SELECT OBJECT_NAME, OBJECT_TYPE, STATUS

2 FROM USER_OBJECTS

3 WHERE OBJECT_NAME IN ('TBLA','TEST_DEPEND')

4 /

OBJECT_NAME OBJECT_TYPE STATUS

-------------- ------------------ -------

TEST_DEPEND PROCEDURE INVALID

TBLA TABLE VALID

Ууупс! (Как поет Бритни Спирс) А, процедура то TEST_DEPEND стала INVALID! Что же делать?! Может вернуть все на круги своя? Пробуем:

ALTER TABLE TBLA DROP COLUMN FIELDC

/

Получаем:

SQL> ALTER TABLE TBLA DROP COLUMN FIELDC

2 /

Таблица изменена.

Снова смотрим состояние объекта:

SQL> SELECT OBJECT_NAME, OBJECT_TYPE, STATUS

2 FROM USER_OBJECTS

3 WHERE OBJECT_NAME IN ('TBLA','TEST_DEPEND')

4 /

OBJECT_NAME OBJECT_TYPE STATUS

------------- ------------------ -------

TEST_DEPEND PROCEDURE INVALID

TBLA TABLE VALID

Ууупс! (I did it again!) Не помогло! Что же делать? Да все просто! Если изменили связанный объект, нужно перекомпилировать вашу процедуру! Вот так:

ALTER PROCEDURE TEST_DEPEND COMPILE

/

Получаем:

SQL> ALTER PROCEDURE TEST_DEPEND COMPILE

2 /

Процедура изменена.

А теперь убедимся, что все пришло на круги своя! Даем запрос:

SQL> SELECT OBJECT_NAME, OBJECT_TYPE, STATUS

2 FROM USER_OBJECTS

3 WHERE OBJECT_NAME IN ('TBLA','TEST_DEPEND')

4 /

OBJECT_NAME OBJECT_TYPE STATUS

-------------- ------------------ -------

TEST_DEPEND PROCEDURE VALID

TBLA TABLE VALID

Надеюсь, ясно, если один объект БД связан с другим и в какой-то момент при изменении одного из них с помощью оператора DDL или как-либо еще - другой объект необходимо переинициализировать! Немного не удобно, зато дешево и сердито! В любом случае учитесь сопровождать свой код, так чтобы не было ошибок! :)

Шаг 96 - PL/SQL - Понятие пакета в языке PL/SQL

Немаловажным фактором является то, что мы с вами уже научились работать с процедурами PL/SQL. Как их создавать, передавать им параметры, изменять, удалять - я думаю это для вас уже не вызывает затруднений. Однако в PL/SQL есть еще одно очень, я бы сказал концептуальное и достаточно интересное понятие, а именно пакеты (package). Еще их называют модулями. Сама концепция пакета в PL/SQL пришла все из того же языка программирования Ada. Пакет позволяет в точном определении хранить связанные объекты в одном месте. Что это значит? Допустим, у вас есть группа функций или процедур которая выполняет, скажем, расчет заработной платы. Как правило, это 20-ть - 30-ть функций и процедур. Такое количество хранимых конструкций как правило приводит к тому, что после отладки вашего проекта, Вы уже смутно представляете себе, что делает каждая функция сама по себе, и как говорил персонаж моего любимого мультфильма - "Не понятно, что где валяется и когда все это кончится!" :) Так вот здесь нам на помощь и приходят пакеты (модули кому как больше нравится). Я думаю, вы все помните такую конструкцию:

.

.

DBMS_OUTPUT. enable;

DBMS_OUTPUT. put_line('HELLO WORLD!');

.

.

Так вот это и есть пакет, который занимается тем что выводит "информацию на экран" (в переносном, смысле!). Если вы помните, то ранее я часто говорил - "Воспользуемся пакетом... бла бла бла", тогда я не акцентировал внимание, а вот сейчас как раз настало время. Дело в том, что при установке сервера Oracle - происходит установка очень большого количества пакетов. Для работы с динамическими запросами DBMS_SQL, для работы с Web пакет DBMS_WEB и т. д. Все это огромное количество готового кода, который разработчики фирмы Oracle предоставляют в ваше распоряжение. К примеру, если посмотреть "глазами" PL/SQL - Developer то, пакет DBMS_OUTPUT выглядит в системе примерно вот так:

96_1.gif (15709 b)

Слева хорошо виден сам пакет, а справа первая сверху строчка "procedure put_line(a varchar2);" и есть как раз функция вывода "на экран". В отличие от процедур и функций, которые могут содержатся локально в блоке или хранится в базе данных, пакеты могут быть только хранимыми и никогда локальными! К слову при использовании пакетов, производительность системы увеличивается. По своей сути модуль представляет собой именованный раздел объявлений. В него могут входить, различные объявления, как то:

Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8