Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Информационное обеспечение управляющих систем реального времени

..pdf
Скачиваний:
3
Добавлен:
15.11.2022
Размер:
3.63 Mб
Скачать

Хранимые процедуры в MICROSOFT SQL SERVER

Хранимые процедуры помогают повысить эффективность, поскольку при их использовании объем пересылаемой между сервером и клиентом информации существенно снижается. Обратная сторона состоит в том, что это увеличивает нагрузку на систему сервера баз данных, так как в этом случае на стороне клиента (приложения) выполняется меньшая часть работы, а на стороне сервера – большая.

Хранимые процедуры позволяют изменять структуру БД и управлять производительностью без переписывания приложений и распространения их обновлений. Хранимая процедура имеет имя и хранится в БД. При первом обращении к процедуре SQL Server генерирует планы компиляции и выполнения, которые хранятся в кеше запроса и повторно используются последующими выполнениями.

Главное назначение процедуры – создание прикладного интерфейса для БД.

Хранимые процедуры Transact-SQL похожи на процедурыиздругихязыковпрограммированиятем, чтоонимогут:

принимать входные параметры и возвращать вызывающей процедуре или пакету ряд значений в виде выходных параметров;

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

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

Чтобы выполнить процедуру, используйте оператор

EXECUTE:

EXEC[ute] {[@return_status =]

211

{[[[server.]database.]owner.]procedur e_name[;number] |

@procedure_name_var} [[@parameter_name =] {value |

@variable [OUTPUT]]

[, [@parameter_name =] {value | @variable [OUTPUT]}]...]

[WITH RECOMPILE]]

EXEC[ute] ({@str_var | 'tsql_string'} [{@str_var | 'tsql_string'}...)}

Выполняет указанную хранимую процедуру с указанными параметрами, возвращая код возврата. Кроме процедур также можно и выполнять и строку символов.

Процедура с входными параметрами

Используйте эту инструкцию для создания постоянной процедуры в текущей базе данных или временной процеду-

ры в базе данных tempdb.

USE AdventureWorks2012; GO

CREATE PROCEDURE HumanResources.uspGetEmployeesTest2

@LastName nvarchar(50), @FirstName nvarchar(50)

AS

SET NOCOUNT ON;

SELECT FirstName, LastName, Department

FROM HumanResources.vEmployeeDepartmentHistory

WHERE FirstName = @FirstName AND LastName = @LastName AND EndDate IS NULL;

GO

В примере показаны различные методы задания значений параметров:

EXECUTE HumanResources.uspGetEmployeesTest2

212

N'Ackerman', N'Pilar'; -- Or

EXEC HumanResources.uspGetEmployeesTest2 @LastName = N'Ackerman', @FirstName = N'Pilar';

GO

-- Or EXECUTE

HumanResources.uspGetEmployeesTest2 @FirstName = N'Pilar', @LastName = N'Ackerman';

GO

Выполнить процедуру можно, нажав кнопку «Выпол-

нить» в окне SQL Server Management Studio [11].

Следующая процедура возвращает два результирующих набора:

CREATE PROCEDURE dbo.uspMultipleResults

AS

SELECT TOP(10) BusinessEntityID, Lastname, FirstName FROM Person.Person;

SELECT TOP(10) CustomerID, AccountNumber FROM Sales.Customer;

GO

Использование параметров, возвращающих табличные значения

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

/* Create a table type. */

213

CREATE TYPE

LocationTableType AS

TABLE

VARCHAR(50), CostRate

( LocationName

INT );

 

GO

 

/* Create a procedure to receive data for the table-valued parameter. */

CREATE PROCEDURE usp_InsertProductionLocation

@TVP LocationTableType READONLY AS

SET NOCOUNT ON

INSERT INTO [AdventureWorks2012].[Production].[Locatio n]

([Name]

,[CostRate]

,[Availability]

,[ModifiedDate])

SELECT *, 0, GETDATE() FROM @TVP;

GO

/* Declare a variable that references the type. */

DECLARE @LocationTVP

AS LocationTableType;

/* Add data to the table variable. */ INSERT INTO @LocationTVP

(LocationName, CostRate) SELECT [Name], 0.00 FROM

[AdventureWorks2012].[Person].[StateProvin

ce];

214

/* Pass the table variable data to a stored procedure. */

EXEC usp_InsertProductionLocation @LocationTVP;

GO

Использование параметра-курсора OUTPUT

В следующем примере используется параметр курсора OUTPUT для возврата курсора, локального относительно процедуры, в вызывающий пакет, процедуру или триггер.

Сначала следует создать процедуру, объявляющую и

открывающую курсор для таблицы Currency:

(

IF

OBJECT_ID

'dbo.uspCurrencyCursor', 'P' ) IS NOT NULL

DROP

 

 

PROCEDURE

dbo.uspCurrencyCursor;

 

 

GO

 

 

PROCEDURE

CREATE

 

 

dbo.uspCurrencyCursor

CURSOR

VARYING

@CurrencyCursor

OUTPUT AS

SET NOCOUNT ON;

SET @CurrencyCursor = CURSOR FORWARD_ONLY STATIC FOR SELECT CurrencyCode, Name FROM Sales.Currency;

OPEN @CurrencyCursor; GO

Затем выполним пакет, в котором объявляется локальная переменная-курсор, выполняется процедура, назначающая курсор локальной переменной, и извлекаются строки из курсора [11].

DECLARE @MyCursor CURSOR;

EXEC dbo.uspCurrencyCursor @CurrencyCursor = @MyCursor OUTPUT;

215

WHILE (@@FETCH_STATUS = 0)

BEGIN;

FETCH NEXT FROM @MyCursor;

END;

CLOSE @MyCursor;

DEALLOCATE @MyCursor;

GO

Хранимые процедуры в Oracle. Вызов процедуры Call

Oracle позволяет хранить блоки PL\SQL как объекты БД в форме хранимых процедур, функций или пакетов. Использование хранимой процедуры увеличивает эффективность клиент-серверной системы по причинам:

Вызов хранимой процедуры из приложения-клиента порождает минимальный сетевой трафик. Приложению нужно не передать серверу весь блок PL\SQL, а лишь вызвать процедуру или функцию со списком параметров.

Хранимые процедуры обеспечивают удобный и эффективный механизм безопасности. Позволяет непривилегированным пользователям получать контролируемый доступ к привилегированным объектам.

Откомпилированные процедуры и их исходные тексты содержатся в БД. Откомпилированная процедура готова к исполнению.

Пример процедуры, вносящей запись в Product и присваивающей первичному ключу c значение nvl(max(tovar.codet), 0)

+1, еслиононезадано:

Procedure InsertRecord(c in out Product.idProduct%type,

n Product.ProductName%type ) is

begin

if c is null then

216

select nvl(max(Product. idProduct), 0) + 1 into c from Product;

end if;

-- Insert the new record

insert into Product (idProduct, ProductName)

values (c, n); end;

Блок с процедурой double и вызовом процедуры double:

DECLARE

in_string VARCHAR2(100):= 'This is my test string.';

out_string VARCHAR2(200);

PROCEDURE double ( original IN VARCHAR2, new_string OUT VARCHAR2 ) AS

BEGIN

new_string:= original || ' + ' || original;

EXCEPTION

WHEN VALUE_ERROR THEN DBMS_OUTPUT.PUT_LINE('Output buffer

not long enough.'); END;

BEGIN

double(in_string, out_string); DBMS_OUTPUT.PUT_LINE(in_string || '

- ' || out_string); END;

/

Пример хранимой процедуры и ее вызов Call:

CREATE OR REPLACE PROCEDURE award_bonus (emp_id NUMBER, bonus NUMBER) AS

commission REAL; comm_missing EXCEPTION;

BEGIN

217

SELECT commission_pct / 100 INTO commission FROM employees

WHERE employee_id = emp_id; IF commission IS NULL THEN RAISE comm_missing;

ELSE

UPDATE employees SET salary = salary + bonus*commission

WHERE employee_id = emp_id; END IF;

EXCEPTION -- exception-handling part starts here

WHEN comm_missing THEN DBMS_OUTPUT.PUT_LINE('This employee

does not receive a commission.'); commission:= 0;

WHEN OTHERS THEN

NULL; -- for other exceptions do nothing

END award_bonus;

/

CALL award_bonus(150, 400); [12]

2.30. Функции, определяемые пользователем. Вызов функции

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

Пользователь может сам создавать функции, называемые пользовательскими или определенными пользователем. Для создания функции пользователь должен иметь разрешение CREATE FUNCTION. Функции не могут изме-

218

нять состояние экземпляра сервера или БД, модифицировать данные в таблице, вызывать функцию с внешним эффектом, создавать временные таблицы и обращаться к ним, выполнять программный код динамически. Функции могут возвращать скалярное или табличное значение. Получают данные из функции с помощью конструкции SELECT.

Функции, определяемые пользователем в SQL Server

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

Применение скалярной, определяемой пользователем функции, вычисляющей неделю по ISO

В следующем примере показано создание определяемой пользовательской функции ISOweek, которая получает в качестве аргумента дату и вычисляет номер недели по ISO. Для правильной работы этой функции перед ее вызовом должна быть выполнена инструкция SET DATEFIRST 1.

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

SELF, OWNER и user_name.

Показан вызов функции. Обратите внимание, что DATEFIRST устанавливается в значение 1.

IF OBJECT_ID (N'dbo.ISOweek', N'FN') IS NOT NULL

DROP FUNCTION dbo.ISOweek; GO

219

CREATE FUNCTION dbo.ISOweek (@DATE datetime)

RETURNS int

WITH EXECUTE AS CALLER AS

BEGIN

DECLARE @ISOweek int;

SET @ISOweek= DATEPART(wk,@DATE)+1 -DATEPART(wk,CAST(DATEPART(yy,@DATE)

as CHAR(4))+'0104');

--Special cases: Jan 1-3 may belong to the previous year

IF (@ISOweek=0) SET

@ISOweek=dbo.ISOweek(CAST(DATEPART(yy,@DAT E)-1

AS

CHAR(4))+'12'+

CAST(24+DATEPART(DAY,@DATE)

AS

CHAR(2)))+1;

 

--Special case: Dec 29-31 may belong to the next year

IF ((DATEPART(mm,@DATE)=12) AND ((DATEPART(dd,@DATE)-

DATEPART(dw,@DATE))>= 28))

SET @ISOweek=1; RETURN(@ISOweek);

END; GO

SET DATEFIRST 1; SELECT

dbo.ISOweek(CONVERT(DATETIME,'12/26/2004', 101)) AS 'ISO Week';

Ниже приводится результирующий набор. ISO Week

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

52

220