double arrow

Создание процедур, функций и модулей

Существуют два основных вида блоков PL/SQL: анонимные и именованные. Анонимные блоки (начинающиеся с DECLARE или с BEGIN) компилируются каждый раз при их использовании. Они не хранятся в базе данных, и их нельзя непосредственно вызывать из других блоков PL/SQL. Программные конструкции, которые рассматриваются ниже (процедуры, функции, модули), являются именованными блоками, они не имеют вышеназванных ограничений. Такие конструкции можно хранить в базе данных и исполнять по мере необходимости.

Процедуры и функции

Процедуры и функции PL/SQL очень похожи на процедуры и функции, используемые в других языках третьего поколения, и обладают аналогичными свойствами. В совокупности процедуры и функции называются подпрограммами (subprogram). В качестве примера рассмотрим следующий фрагмент программы создания процедуры в базе данных:

 

CREATE OR REPLACE PROCEDURE AddNewStudent ( p_FirstName students.first_name%TYPE, p_LastName students.last_name%TYPE, p_Major students.major%TYPE) AS BEGIN /* Внесем новую строку в таблицу students. Воспользуемся последовательностью studet_sequence для генерации идентификатора нового студента*/ INSERT INTO students (ID, first_name, last_name, major) VALUES (student_sequence.nextval, p_FirstName, p_LastName, p_Major); END AddNewStudent; /

 

Созданную процедуру можно вызвать из другого блока PL/SQL:

 

BEGIN AddNewStudent('Василий', 'Николаев', 'Информатика'); END; /

 

В этом примере демонстрируется ряд важных аспектов:

- Процедура AddNewStudent создается при помощи оператора CREATE OR REPLACE PROCEDURE. После создания процедуры она сначала компилируется, а затем сохраняется в базе данных в скомпилированном виде. Скомпилированный код можно впоследствии выполнить из другого блока PL/SQL. Исходный код процедуры также сохраняется в базе данных.

- При вызове процедуры ей можно передавать параметры. В рассмотренном примере процедуре во время ее выполнения передаются имя, фамилия и профилирующий предмет студента.

- Вызов процедуры — это оператор PL/SQL. При вызове процедуры управление программой передается первому исполняемому оператору внутри нее. Когда процедура заканчивается, управление возвращается оператору, следующему за вызовом процедуры. В этом смысле процедуры PL/SQL функционируют точно так же, как и процедуры других языков третьего поколения.

- Процедура — это блок PL/SQL, в состав которого входят раздел объявлений, выполняемый раздел и раздел обработки исключительных ситуаций. Как и в анонимных блоках, необходимым здесь является только выполняемый раздел. Например, в процедуре AddNewStudent содержится лишь выполняемый раздел.

Создание процедуры

Синтаксис оператора CREATE [OR REPLACE] PROCEDURE следующий:

CREATE [OR REPLACE] PROCEDURE имя_процедуры

[ (аргумент [{IN | OUT | IN OUT}] тип,

аргумент [{IN | OUT | IN OUT}] тип)] {IS | AS}

тело_ процедуры;

где имя_процедуры – это имя создаваемой процедуры, аргумент – имя параметра процедуры, тип – это тип соответствующего параметра, а тело_процедуры – блок PL/SQL, в котором содержится код процедуры. Список аргументов является необязательным; в этом случае скобки отсутствуют как в объявлении, так и в вызове процедуры.

Чтобы изменить текст процедуры, необходимо удалить и повторно создать ее. Во время разработки процедур эта операция выполняется довольно часто, поэтому ключевые слова OR REPLACE (или заменить) позволяют выполнить такую операцию за один раз. Если процедура существует, она сначала удаляется безо всякого предупреждения (для удаления процедур используется команда DROP PROCEDURE).

Cтруктура оператора создания процедуры такова:

CREATE OR REPLACE PROCEDURE имя_процедуры

[список_парометров] AS

/* Раздел объявлений */

BEGIN

/* Выполняемый раздел */

EXCEPTION

/* Раздел исключительных ситуаций */

END [имя_процедуры];

Создание функции

Функции похожи на процедуры. И те, и другие получают некоторые параметры того или иного вида (параметры описываются ниже). Функции и процедуры — это различные формы блоков PL/SQL, в состав каждого из которых могут входить раздел объявлений, выполняемый раздел и раздел исключительных ситуаций. Как функции, так и процедуры можно хранить в базе данных или объявлять в блоке. Однако вызов процедуры является оператором PL/SQL, в то время как вызов функции — это часть некоторого выражения. Ниже приведен пример вызова функции, возвращающей количество студентов в группе.

CREATE OR REPLACE FUNCTION CountStudents RETURN NUMBER IS v_Students NUMBER; BEGIN -- Получим текущее и максимальное число студентов в группе. SELECT count(*) INTO v_Students FROM students; RETURN v_Students; END CountStudents; /

Для вызова функции выполните:

 

SELECT CountStudents FROM dual;

 

Синтаксис функции, похож на синтаксис создания процедуры:

CREATE [OR REPLACE] FUNCTION имя_функции

[(аргумент [{IN | OUT |IN OUT}] тип,

аргумент [{1Н \ OUT |INOUT}] тип)]

RETURN возвращаемый_тип {IS | AS}

тело_функции;

 

где имя_функции — это имя функции, аргумент и тип аналогичны аргументу и типу, указываемым при создании процедуры, возвращаемый_тип — это тип значения, возвращаемого функцией, а тело_функции — блок PL/SQL, содержащий программный код данной функции. Для тела функции применимы те же правила, что и для тела процедуры. Например, имя функции можно при желании указать после закрывающего END.

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

Внутри тела функции оператор RETURN используется для возврата управления программой в вызывающую среду с некоторым значением. Общий синтаксис оператора RETURN:

RETURN выражение;

где выражение — это возвращаемое значение. Значение выражения преобразуется в тип, указанный в команде RETURN при описании функции, если, конечно, это значение уже не имеет данный тип. При выполнении оператора RETURN управление программой сразу же возвращается в вызывающую среду.

В функции может быть несколько операторов RETURN, хотя выполняться будет только один из них. Отсутствие в функции оператора RETURN является ошибкой.

Модуль (package) – еще одно средство, пришедшее в PL/SQL из языка программирования Ada. Модуль – это конструкция PL/SQL, которая позволяет хранить связанные объекты в одном месте. Модуль состоит из двух частей: описания и тела. Они хранятся по отдельности в словаре данных. В отличие от процедур и функций, которые могут содержаться локально в блоке или храниться в базе данных, модули могут быть только хранимыми и никогда локальными. Помимо того, что модули позволяют группировать связанные объекты, они полезны еще и тем, что ограничений, налагаемых зависимостями, в них меньше, чем в хранимых подпрограммах.

В сущности, модуль представляет собой именованный раздел объявлений. Все, что может входить в состав раздела объявлений блока, может входить и в модуль: процедуры, функции, курсоры, типы и переменные.

Размещение их в модуле полезно тем, что это позволяет обращаться к ним из других блоков PL/SQL, поэтому в модулях можно описывать глобальные переменные PL/SQL (внутри одного сеанса работы с базой данных).

В описании, или спецификации, модуля (package specification), называемом также заголовком модуля (package header), содержится информация о составе модуля, однако в описание не входит текст процедур. Рассмотрим пример:

 

CREATE OR REPLACE PACKAGE StudPackage AS --Добавляет нового студента. PROCEDURE AddNewStudent (p_FirstName students.first_name%TYPE, p_LastName students.last_name%TYPE, p_Major students.major%TYPE); -- Удаляет указанного студента PROCEDURE RemoveStudent(p_StudetitID IN students. id%TYPE); END StudPackage; /

 

Элементы модуля (описания процедур и функций, переменные и т.д.) аналогичны тому, что указывается в разделе объявлений анонимного блока. Для заголовка модуля действуют те же синтаксические правила, что и для раздела объявлений, за исключением объявлений процедур и функций. Перечислим эти правила:

- Элементы модуля могут указываться в любом порядке. Однако, как и в разделе объявлений, объект должен быть объявлен до того, как на него будут произведены ссылки. Например, если частью предложения WHERE курсора является некоторая переменная, она должна быть объявлена до объявления курсора. Совсем не обязательно, чтобы присутствовали элементы всех видов.

- Объявления всех процедур и функций должны быть предварительными. В предварительном объявлении (forward declaration) описываются подпрограмма и ее аргументы (если есть), но не включается программный текст. В этом отличие модуля от раздела объявлений блока, где могут находиться как предварительные объявления, так и текст процедур и функций. Программный текст процедур и функций модуля содержится в теле этого модуля.

Тело модуля (package body) — это объект словаря данных, хранящийся отдельно от заголовка модуля. Тело модуля нельзя скомпилировать, если ранее не был успешно скомпилирован заголовок. В теле содержится текст подпрограмм, предварительно объявленных в заголовке модуля. В нем могут находиться также дополнительные объявления, глобальные для тела модуля, но не видимые в его описании. Тело модуля ClassPackage показано в следующем примере:

 

CREATE OR REPLACE PACKAGE BODY StudPackage AS   -- Добавляет нового студента. PROCEDURE AddNewStudent (p_FirstName students.first_name%TYPE, p_LastName students.last_name%TYPE,  p_Major students.major%TYPE) AS BEGIN /* Внесем новую строку в таблицу students. */ INSERT INTO students (ID, first_name, last_name, major) VALUES (student_sequence.nextval,       p_FirstName, p_LastName, p_Major); END AddNewStudent; -- Удаляет указанного студента PROCEDURE RemoveStudent(p_StudetitID IN students. id%TYPE) IS BEGIN DELETE FROM students WHERE student_id = p_StudentID; END RemoveStudent; END StudPackage; /

В теле модуля содержится программный текст для предварительных объявлений, сделанных в заголовке модуля, и могут также находиться дополнительные переменные, курсоры, типы и подпрограммы.

Тело модуля не является обязательной его частью. Если в заголовке не указаны какие-либо процедуры или функции (а только переменные, курсоры, типы и т.д.), тело можно не создавать. Такой способ полезен для объявления глобальных переменных, поскольку все объекты модуля видимы вне его пределов.

Любое предварительное объявление в заголовке модуля должно быть раскрыто в его теле. Описание процедуры или функции должно быть таким же и включать в свой состав имя подпрограммы, имена ее параметров и вид каждого параметра.

Любой объект, объявленный в заголовке модуля, находится в области действия и видим вне этого модуля. При обращении к объекту нужно указать имя модуля. Например, можно вызвать процедуру ClassPackage.RemoveStudent из блока PL/SQL:

 

BEGIN StudPackage.RemoveStudent(1); END; /

 

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




Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



Сейчас читают про: