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 выглядит в системе примерно вот так:

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


