Шаг 94 - PL/SQL - Функции и процедуры - размещение

Мы с вами уже многое знаем о процедурах и функциях, вот теперь давайте поговорим о том, где находятся и хранятся откомпилированные процедуры и функции. После того, как команда CREATE OR REPLACE создает процедуру или функцию, она сразу сохраняется в БД, в скомпилированной форме, которая называется p-кодом (p-code). В p-коде содержатся все обработанные ссылки подпрограммы, а исходный текст преобразован, в вид удобный для чтения системой поддержки PL/SQL. При вызове хранимой процедуры p-код считывается с диска и выполняется. Собственно сам P-код аналогичен объектному коду генерируемому компиляторами языков программирования высокого уровня. В P-коде содержатся обработанные ссылки на объекты (это свойство ранней привязки переменных, о которой мы говорили с вами ранее) по этому выполнение P-кода является сравнительно не дорогой (нересурсоемкой) операцией. Да к слову напомню, что удалить код процедуры или функции из вашей БД (схемы) можно применив, оператор DROP - вот таким образом (в шаге 87 мы уже это делали):

---- DROP PROCEDURE имя_процедуры ------------------------

---- DROP FUNCTION имя_функции ---------------------------

Теперь давайте вспомним каким образом можно получить информацию о наличии процедур и их работоспособности. Самое простое это выполнить такой запрос к системному представлению USER_OBJECTS вот так:

SELECT OBJECT_NAME, OBJECT_TYPE, STATUS 
FROM USER_OBJECTS
/

В моем случае получилось следующее:

SQL> SELECT OBJECT_NAME, OBJECT_TYPE, STATUS
  2  FROM USER_OBJECTS
  3  /

OBJECT_NAME      OBJECT_TYPE        STATUS
---------------- ------------------ -------
BOOL_TO_CHAR     FUNCTION           VALID
BOOL_TO_CHARTWO  FUNCTION           VALID
BOYS             TABLE              VALID
CUSTOMERS        TABLE              VALID
FACTORIAL        FUNCTION           VALID
GIRLS            TABLE              VALID
OFFICES          TABLE              VALID
ORDERS           TABLE              VALID
PRODUCTS         TABLE              VALID
PTEST            PROCEDURE          VALID
SALESREPS        TABLE              VALID
SYS_C003505      INDEX              VALID
SYS_C003506      INDEX              VALID
SYS_C003507      INDEX              VALID
SYS_C003511      INDEX              VALID
SYS_C003512      INDEX              VALID
SYS_C003513      INDEX              VALID
SYS_C003515      INDEX              VALID
TESTINOUT        PROCEDURE          VALID
TESTOUT          PROCEDURE          VALID

OBJECT_NAME      OBJECT_TYPE        STATUS
---------------- ------------------ -------
TESTPRG          PROCEDURE          VALID
TESTPRGTWO       PROCEDURE          VALID
TESTPRM          PROCEDURE          VALID
TEST_POZ         PROCEDURE          VALID

24 строк выбрано.

Я включил только три столбца представления, которые дают основную информацию, но если хотите можете использовать все столбцы. Хорошо видно, что у нас с вами все объекты имеют статус VALID, то есть исправны. А, вот как, например увидеть текст хранимой процедуры или функции, для этого используйте системное представление USER_SOURCE. Давайте к примеру выведем текст функции из прошлого шага - FACTORIAL:

SELECT * FROM USER_SOURCE
WHERE NAME = 'FACTORIAL'
/

Получаем:

SQL> SELECT * FROM USER_SOURCE
  2  WHERE NAME = 'FACTORIAL'
  3  /

NAME       TYPE       LINE TEXT
---------- ---------- ----------------------------------------------------
FACTORIAL  FUNCTION   1 FUNCTION FACTORIAL(NUM IN NUMBER) RETURN NUMBER
FACTORIAL  FUNCTION   2 IS
FACTORIAL  FUNCTION   3 
FACTORIAL  FUNCTION   4 BEGIN
FACTORIAL  FUNCTION   5 
FACTORIAL  FUNCTION   6 IF (NUM <=1) THEN
FACTORIAL  FUNCTION   7  RETURN (NUM);
FACTORIAL  FUNCTION   8 ELSE
FACTORIAL  FUNCTION   9  RETURN (NUM * FACTORIAL(NUM-1));
FACTORIAL  FUNCTION   10 
FACTORIAL  FUNCTION   11 END IF;
FACTORIAL  FUNCTION   12 
FACTORIAL  FUNCTION   13 END FACTORIAL;

13 строк выбрано.

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

CREATE OR REPLACE PROCEDURE TESTERR(NUM IN NUMBER)
IS

K NUMBER;

BEGIN

K := NUM

END TESTERR;
/

Получаем:

SQL> CREATE OR REPLACE PROCEDURE TESTERR(NUM IN NUMBER)
  2  IS
  3  
  4  K NUMBER;
  5  
  6  BEGIN
  7  
  8  K := NUM
  9  
 10  END TESTERR;
 11  /

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

Правильно, в данном случае мы забыли поставить ";" после завершения строки K := NUM. Вот теперь давайте дадим такой запрос:

SELECT OBJECT_NAME, OBJECT_TYPE, STATUS 
FROM USER_OBJECTS
WHERE STATUS = 'INVALID'
/

Получаем:

SQL> SELECT OBJECT_NAME, OBJECT_TYPE, STATUS
  2  FROM USER_OBJECTS
  3  WHERE STATUS = 'INVALID'
  4  /

OBJECT_NAME                OBJECT_TYPE        STATUS
-------------------------- ------------------ -------
TESTERR                    PROCEDURE          INVALID

Странно, процедура вроде бы создана, ее p-код присутствует, но она не исправна! Попробуем вызвать ее:

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  /

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

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


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