Хранимые процедуры и функции. Типы параметров, синтаксис описания формальных параметров
SQL Server
Хранимая процедура - это подпрограмма, состоящая из SQL операторов и команд T-SQL. Хранимая процедура сохраняется на сервере и выполняется по команде пользователя или вызывается из блока T-SQL. План выполнения процедуры подготавливается во время запуска процедуры, поэтому собственно выполнение процедуры происходит очень быстро. Хранимая процедура может:
- Содержать параметры (аргументы);
- Вызывать другие процедуры;
- Возвращать свой статус вызывающей процедуре или модулю T_SQL, указывающий на успешное окончание или ошибку, и в случае ошибки на ее причину;
- Возвращать значения параметров вызывающей процедуре или модулю T-SQL ;
Синтаксис для создания хранимой процедуры:
create procedure [владелец.]название_процедуры[;номер] [ [(] @название_параметра тип_данных [= default] [output] [, @название_параметра тип_данных [= default] [output]]...[)]] [with recompile] as sql_операторы
[execute] [@return_status =] [[[сервер.]база_данных.]владелец.]название_процедуры[;номер] [[@название_параметра = ] значение | [@название_параметра = ] @переменная [output] [,[@название_параметра = ] значение | [@название_параметра = ] @переменная [output]...]] [with recompile]
Параметры
Параметр - это аргумент хранимой процедуры. Один или несколько параметров могут быть объявлены в операторе создания процедуры. Значение каждого параметра, объявленного в операторе create procedure, должно указываться пользователем в момент вызова процедуры.
Названиям параметров должен предшествовать символ "@", а сами эти названия должны соответствовать правилам, установленным для идентификаторов. Для всех параметров должен быть указан системный или пользовательский тип данных, и если необходимо длина этого типа данных. Названия параметров являются локальными по отношению к содержащей их процедуре; такие же названия можно использовать для параметров в другой процедуре.
В операторе create procedure для параметра можно указать значение, принимаемое по умолчанию. Это значение, которое может быть любой константой, используется в качестве аргумента процедуры, если для этого параметра не было указано никакого значения.
CREATE proc dbo.tran_Begin /* * Инициализация транзакции * Если процедура выполняется внутри транзакции, то создается savepoint * Иначе инициализируется транзакция * На выходе передается null для транзакции и имя точки сохранения для savepoint */ (@trName DObjectName output, @explicitSavepointNameFlag DLogical = 0) as declare @d Datetime begin -- return 0 if @@trancount = 0 begin select @trName = null begin transaction end else begin -- если не задано имя и не установлен флаг использования переданного имени, то генерим имя if @explicitSavepointNameFlag = 0 or @trName is null begin select @d = getdate() select @trName = 'tr_'+ISNULL(convert(varchar, @@nestlevel), '')+'_'+ISNULL(convert(varchar(50), rand(datepart(mm, @d)*100000+datepart(ss, @d)*1000+datepart(ms, @d))), '') end save tran @trName end if @@error <> 0 begin -- ошибка создания транзакции return 5 end return 0 end CREATE proc dbo.tran_Commit /* * Подтверждение транзакции * Работает в паре с tran_Begin * на вход передается имя точки сохранения (транзакции), возвращенное tran_Begin * Если вызов идет из транзакции и @trName равно null, то выполняется commit, * иначе ничего не делается */ (@trName DObjectName) as begin if @@trancount > 0 and @trName is null begin commit if @@error <> 0 begin -- ошибка подтверждения транзакции return 6 end end return 0 end CREATE proc dbo.tran_Rollback /* * Откат транзакции * Работает в паре с tran_Begin * на вход передается имя точки сохранения (транзакции), возвращенное tran_Begin * Если вызов идет из транзакции и @trName равно null, то выполняется откат всей транзакции, * иначе выполняется откат до точки сохранения @trName */ (@trName DObjectName) as begin if @@trancount > 0 begin if @trName is null rollback tran else rollback tran @trName if @@error <> 0 begin -- ошибка отката транзакции return 7 end end return 0 endЛистинг 10.1.
Возврат результатов
Хранимые процедуры сообщают свой "статус возврата", который указывает, была ли выполнена процедура полностью, или нет, а также причины неудачи. Это значение может храниться в переменной, которая передается процедуре при ее вызове, и использоваться в последующих операторах Transact-SQL. Другой способ возврата информации из хранимых процедур состоит в возврате значений через выходные параметры. Параметры, определенные как выходные, в операторе create procedure (создать процедуру) или execute (выполнить) используются для возврата значений в место вызова процедуры. Затем с помощью условных операторов можно проверить возвращаемое значение.
Код возврата и выходные параметры позволяют разделить хранимые процедуры на модули. Группа SQL операторов, которые используются несколькими хранимыми процедурами, могут быть объединены в одну процедуру, которая сообщает свой статус выполнения или значения своих параметров вызывающей процедуре. Например, многие системные процедуры, поставляемые с SQL Сервером, обращаются к процедуре, которая проверяет являются ли указанные параметры правильными идентификаторами.
Если в операторах create procedure и execute указывается опция output в названии параметра, то процедура возвращает значение этого параметра вызывающему объекту. Этим объектом может быть SQL пакет или другая хранимая процедура, которые используют возвращаемые значения в своей дальнейшей работе. Если возвращаемые параметры используются в операторе execute, который является частью пакета, то значения возвращаемых параметров вместе с заголовком выводятся на экран перед выполнением последующих операторов пакета.
declare @tranName DObjectName declare @retCode integer begin execute tran_Begin @tranName output select @tranName .........................................
Oracle
Создание процедур
create or replace procedure my_proc(i in number := 123,
j out number, k in out number /* error := 123 */)
as
begin
dbms_output.put_line('i = ' || i);
dbms_output.put_line('j = ' || j);
dbms_output.put_line('k = ' || k);
if i is null then
return;
end if;
-- error
-- i := 10;
j := 20;
k := 30;
end;
create or replace procedure my_proc_error
(i number /* error (1) */, s varchar2 /* error (10) */)
as
begin
null;
end;
declare
a number;
b number;
c number;
begin
a := 1;
b := 2;
c := 3;
my_proc(a, b, c);
dbms_output.put_line('a = ' || a);
dbms_output.put_line('b = ' || b);
dbms_output.put_line('c = ' || c);
end;Создание функций
create or replace function my_fun(i in number) return number
as
j number;
begin
j := i+10;
return j;
end;
declare
a number;
begin
a := 12+my_fun(10);
dbms_output.put_line('a = ' || a);
end;
create or replace function my_fun(i in number) return number
as
j number;
procedure p(n in out number)
as
begin
n := n+i+j;
end;
begin
j := 3;
p(j);
j := j+i+10;
return j;
end;
declare
a number;
begin
a := 12+my_fun(10);
dbms_output.put_line('a = ' || a);
end;Вызов процедур и функций
create or replace procedure my_p
(s varchar2, i number := 10, j number := 20)
as
begin
null;
end;
declare
a number;
b number;
s varchar2(100);
begin
my_p(s);
my_p(s, a);
my_p(s, a, b);
my_p(s=>s, j=>b);
my_p(s, j=>b);
end;
