СОЗДАНИЕ ХРАНИМЫХ ПРОЦЕДУР И ТРИГГЕРОВ
В MS SQL SERVER
Методические указания к выполнению практической работы по курсу «Современные технологии управления базами данных»
для студентов направления 230400.62 очной, заочной и заочно-сокращенной форм обучения
Цель работы: научиться создавать хранимые процедуры и триггеры в MS SQL Server
ОСНОВНЫЕ ПОНЯТИЯ
1. Хранимые процедуры.
Хранимые процедуры – предварительно скомпилированная группа команд SQL. Хранимые процедуры имеют имена и обрабатываются как единый рабочий блок. Хранимые процедуры принимают входные параметры и возвращают значения в вызывающую процедуру или команду.
Преимущества хранимых процедур:
-увеличение скорости выполнения. Хранимые процедуры оптимизируются при первой компиляции, это позволяет им запускаться с меньшими издержками по сравнению с командами.
-более быстрый доступ к данным. Хранимые процедуры оптимизированы для наиболее эффективной обработки данных.
-модульное программирование.
-обеспечение целостности базы данных, т.к. клиенты не используют собственных команд.
Усовершенствованный механизм безопасности. Можно предоставить
права выполнения хранимой процедуры пользователю.
Типы хранимых процедур:
-системные (могут только выполняться, предоставляют сведения о базе данных и пользователях)
-пользовательские.
Системные хранимые процедуры.
При создании базы данных автоматически создаются системные таблицы, которые хранят определения объектов базы данных, пользователях и правах доступа. Пользователи получают доступ к системным базам данных только через системные процедуры.
Имена всех системных процедур начинаются с префикса ‘sp_’.
Системные процедуры располагаются в базе данных master.
Пример:
Sp_databasesперечисляет все базы данных, доступные на данном сервере
Sp_server_infoвыдает информацию о сервере, такую как используемый набор символов, версию.
Sp_tables – перечисляет все объекты, к которым можно обратиться с запросом в текущей среде.
Пользовательские хранимые процедуры Все хранимые процедуры создаются в текущей базе данных. Чтобы
создать процедуру, необходимо право на выполнение команды создания процедуры, которое по умолчанию присвоено владельцу базы данных.
Синтаксис:
CREATE PROCEDURE <имя процедуры> @имя_параметра тип_данных as
Пример: Создадим процедуру, которая по буквам ms или mr будет выводить значения ‘woman’, ‘man’ соответственно
CREATE PROCEDURE checkGender (@name char(10) as
If (substring (@name, 1, 3)=’ms’) print ‘woman’
Else begin
if (substring (@name, 1, 3)=’mr’) print ‘man’) end
Запуск хранимой процедуры осуществляется с помощью команды
EXECUTE (или EXEC) <имя процедуры> (значения, передаваемые параметрам)
Пример
EXECUTE checkGender (‘ms.Olive’)
Использование локальных переменных внутри хранимой процедуры Пример
CREATE TABLE mytable
(
column1 int, column2 char(10)
)
CREATE PROCEDURE InsertRows @start_value int
AS
DECLARE |
@loop_counter int, @start_val int |
SET |
@start_val = @start_value – 1 |
SET |
@loop_counter = 0 |
WHILE (@loop_counter < 5)
BEGIN
INSERT INTO mytable VALUES (@start_val + 1, "new row") SET @start_val = @start_val + 1
SET @loop_counter = @loop_counter + 1
END
Выполним эту хранимую процедуру с начальным значением 1
EXECUTE InsertRows 1
В таблице mytable получим 5 записей column1 column2
-----------------------
1new row
2new row
3new row
4new row
5new row
После завершения хранимой процедуры переменные @loop_counter и @start_val уже недоступны.
Использование RETURN
Вы можете возвращаться из любой точки хранимой процедуры в вызывающую программу с помощью ключевого слова RETURN,
обеспечивающего безусловный выход из процедуры. RETURN можно также использовать для выхода из пакета или блока операторов. При выполнении оператора RETURN в хранимой процедуре работа процедуры прекращается в этой точке, и происходит переход к следующему оператору вызывающей программы. Операторы, следующие после RETURN в хранимой процедуре,
не выполняются. С помощью RETURN вы можете также возвращать целое значение.
Пример. Создадим процедуру GetUnitPrice, которая проверяет, было ли задано входное значение, и если нет, то выводит сообщение для пользователя и возвращается в вызывающую программу. Для этого определим входной параметр со значением по умолчанию NULL и затем будем проверять это значение в процедуре; если входной параметр имеет значение NULL, это означает, что входное значение не задано.
CREATE PROCEDURE GetUnitPrice @prod_id int = NULL
AS
IF @prod_id IS NULL
BEGIN
PRINT "Please enter a product ID number"
RETURN
END
ELSE
BEGIN
SELECT UnitPrice
FROM |
Products |
WHERE |
ProductID = @prod_id |
END |
|
Пример. Рассмотрим использование RETURN для возврата значения в вызывающую программу. Возвращаемое значение должно быть целым. Это может быть константа или переменная. Вы должны объявить в вызывающей программе переменную, в которой будет храниться возвращаемое значение для дальнейшего использования в этой программе. Например, следующая процедура возвратит значение 1, если цена единицы продукции для продукта,
указанного во входном параметре, меньше $100; иначе она возвратит значение 99.
CREATE PROCEDURE CheckUnitPrice @prod_id int
AS
IF (SELECT UnitPrice
FROM Products
WHERE ProductID = @prod_id) < 100
RETURN 1
ELSE
RETURN 99
Для вызова этой хранимой процедуры и использования возвращаемого значения объявите в вызывающей программе переменную и приравняйте ее возвращаемому значению хранимой процедуры (указав значение 66 в ProductID для входного параметра):
DECLARE @return_val int
EXECUTE @return_val = CheckUnitPrice 66
IF (@return_val = 1) PRINT "Unit price is less than $100"
Удаление хранимых процедур выполняется с помощью команды
DROP PROCEDURE
2. ТРИГГЕРЫ Триггер – это специальный тип хранимой процедуры, которая
запускается автоматически системой SQL Server при модифицировании какой-либо таблицы одним из трех операторов: UPDATE, INSERT или
DELETE. Триггеры, как другие хранимые процедуры, могут содержать простые или сложные операторы T-SQL. В отличие от других типов хранимых процедур триггеры запускаются автоматически при указанных модификациях данных; их нельзя запустить вручную по имени. Когда происходит запуск триггера, говорят, что он активизируется (fire) . Триггер создается по одной таблице базы данных, но он может осуществлять доступ и к другим таблицам и объектам других баз данных. Триггеры нельзя создать по временным таблицам или системным таблицам, а только по определенным пользователем таблицам или представлениям. Таблица, по которой определяется триггер, называется таблицей триггера.
Существует пять типов триггеров: UPDATE, INSERT, DELETE, INSTEAD OF и AFTER. Как следует из названий, триггер UPDATE
активизируется, когда выполняются изменения (обновления) в какой-либо таблице, триггер INSERT активизируется, когда происходит вставка данных в таблицу и триггер DELETE активизируется, когда из таблицы удаляются данные. Триггер INSTEAD OF выполняется вместо операции вставки,
обновления или удаления. Триггер AFTER активизируется после какой-либо запускающей операции и обеспечивает механизм управления порядком выполнения нескольких триггеров. Операции обновления, вставки и удаления называются событиями модификации данных. Можно создать триггер, который активизируется при возникновении более чем одного события модификации данных. Например, вы можете создать триггер,
который будет активизироваться, когда происходит выполнение оператора
UPDATE или INSERT, и такой триггер мы будем называть триггером
UPDATE/INSERT.
Правила работы с триггерами:
Триггеры запускаются только после завершения оператора, который вызвал их активизацию. Например, UPDATE-триггер не будет активизироваться, пока не будет выполнен оператор UPDATE.
Если какой-либо оператор пытается выполнить операцию, которая нарушает какое-либо ограничение по таблице или является причиной какой-
то другой ошибки, то связанный с ним триггер не будет активизирован.
Триггер рассматривается как часть одной транзакции вместе с оператором, который вызывает его. Поэтому из триггера можно вызвать оператор отката, и этот оператор выполнит откат как триггера, так и соответствующего события модификации данных. Кроме того, при возникновении серьезной ошибки, такой как разъединение с пользователем, SQL Server автоматически выполнит откат всей транзакции.
Триггер активизируется только один раз для одного оператора, даже если этот оператор влияет на несколько строк данных.
Создание триггеров синтаксис:
CREATE TRIGGER имя_триггера
ON {таблица | представление}
[WITH ENCRYPTION]
{FOR | AFTER | INSTEAD OF} {[DELETE] [,] [INSERT] [,] [UPDATE]}
[WITH APPEND]
[NOT FOR REPLICATION]
AS
оператор_sql [...n]
При создании триггера вы имеете доступ к двум временным таблицам с именами deleted и inserted. Их называют таблицами, но они отличаются от реальных таблиц баз данных. Они хранятся в памяти, а не на диске.
Эти две таблицы имеют одинаковую структуру с таблицей (одинаковые колонки и типы данных), по которой определяется данный триггер. Таблица deleted содержит копии строк, на которые повлиял оператор DELETE или
UPDATE. Строки, удаляемые из таблицы данного триггера, перемещаются в таблицу deleted. После этого к данным таблицы deleted можно осуществлять доступ из данного триггера. Таблица inserted содержит копии строк,
добавленных к таблице данного триггера при выполнении оператора INSERT
или UPDATE. Эти строки добавляются одновременно в таблицу триггера и в таблицу inserted. Поскольку оператор UPDATE обрабатывается как DELETE,
после которого следует INSERT, то при использовании оператора UPDATE
старые значения строк копируются в таблицу deleted, а новые значения строк
– в таблицу триггера и в таблицу inserted.
Пример. Создадим простую таблицу с определенным по ней триггером, который печатает определенный текст при каждой модификации.
Программа T-SQL для создания этой таблицы имеет следующий вид:
USE MyDB
GO
CREATE TABLE Bicycle_Inventory
( |
|
|
make_name |
char(10) |
NOT NULL, |
make_id |
tinyint |
NOT NULL, |
model_name |
char(12) |
NOT NULL, |
model_id |
tinyint |
NOT NULL, |
in_stock |
tinyint |
NOT NULL, |
on_order |
tinyint |
NULL, |
) |
|
|
CREATE TRIGGER Print_Update
ON Bicycle_Inventory
FOR UPDATE
AS
PRINT "The Bicycle_Inventory table was updated"
Чтобы проверить триггер, выполним вставку строки в эту таблицу и
затем модифицируем ее:
INSERT INTO Bicycle_Inventory VALUES ("Trek",1,"5500",5,1,0)
GO
UPDATE Bicycle_Inventory
SET |
make_id = 2 |
WHERE |
model_name = "5500" |
GO
Будет возвращено сообщение "The Bicycle_Inventory table was updated",
так как в результате выполнения оператора UPDATE был запущен триггер. В
данном примере мы задали в нашем триггере вывод сообщения, чтобы можно было увидеть работу этого триггера. Но обычно не требуется, чтобы триггер возвращал выходные данные. Однако в определенных обстоятельствах это может оказаться полезным. Например, предположим, что вы создаете триггер типа UPDATE, который выполняет свои операторы, только когда в указанную колонку заносится определенное значение, но эта модификация происходит неверно. Если добавить в триггер оператор PRINT, который выводит значение этой колонки до выполнения других операторов триггера,
это, видимо, поможет определить, где лежит источник проблемы – в логике самого триггера или в модифицируемых данных.
Пример. Создадим триггер типа INSERT (триггер, который активизируется при выполнении оператора INSERT) по таблице sales. Этот триггер при вставке строки в таблицу sales будет модифицировать колонку ytd_sales в таблице titles добавляя в нее значение, которое было помещено в колонку qty таблицы sales. Этот триггер запрашивает таблицу inserted, чтобы получить значение qty, которое было помещено в таблицу sales. Мы включим в этот запрос оператор SELECT *, с помощью которого увидим, что содержит таблица inserted.
