Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Розділ 6.doc
Скачиваний:
0
Добавлен:
01.03.2025
Размер:
453.63 Кб
Скачать
  1. Програмування тригера

При виконанні команд додавання, зміни і видалення записів сервер створює дві спеціальні таблиці: inserted і deleted. У них містяться списки рядків, які будуть вставлені або видалені після закінчення транзакції. Структура таблиць inserted і deleted ідентична структурі таблиць, для якої визначається тригер. Для кожного тригера створюється свій комплект таблиць inserted і deleted, тому ніякий інший тригер не зможе дістати до них доступ. Залежно від типу операції, що викликала виконання тригера вміст таблиць inserted і deleted може бути різним:

команда INSERT - в таблиці inserted містяться всі рядки, які користувач намагається вставити в таблицю; у таблиці deleted не буде жодного рядка; після завершення тригера всі рядки з таблиці inserted перемістяться в початкову таблицю;

команда DELETE - в таблиці deleted міститимуться всі рядки, які користувач спробує видалити; тригер може перевірити кожен рядок і визначити, чи дозволено її видалення; у таблиці inserted не опиниться жодного рядка;

команда UPDATE - при її виконанні в таблиці deleted знаходяться старі значення рядків, які будуть видалені при успішному завершенні тригера. Нові значення рядків містяться в таблиці inserted. Ці рядки додадуться в початкову таблицю після успішного виконання тригера.

Для отримання інформації про кількість рядків, яка буде змінено при успішному завершенні тригера, можна використовувати функцію @@ROWCOUNT\ вона повертає кількість рядків, оброблених останньою командою. Слід підкреслити, що тригер запускається не при спробі змінити конкретний рядок, а у момент виконання команди зміни. Одна така команда впливає на множину рядків, тому тригер повинен обробляти всі ці рядки.

Якщо тригер виявив, що з 100 рядків, що вставляються, змінних або таких, що видаляються, тільки одна не задовольняє тим або іншим умовам, то жодний рядок не буде вставлений, змінений або видалений. Така поведінка обумовлена вимогами транзакції - мають бути виконані або всі модифікації, або жодна.

Тригер виконується неявно як певна транзакція, тому усередині тригера допускається застосування команд управління транзакціями. Зокрема, при виявленні порушення обмежень цілісності для переривання виконання тригера і відміни всіх змін, які намагався виконати користувач, необхідно використовувати команду ROLLBACK TRANSACTION.

Для отримання списку колонок, змінених при виконанні команд INSERT або UPDATE, що викликали виконання тригера, можна використовувати функцію COLUMNSJJP DATED (). Вона повертає двійкове число, кожен біт якого, починаючи з молодшого, відповідає одній колонці таблиці (в порядку проходження колонок при створенні таблиці). Якщо біт встановлений в значення «1», то відповідна колонка бувла змінена. Крім того, факт зміни клонки визначає і функція UPDATE (ім’я колонки). Для видалення тригера використовується команда:

DROP TRIGGER {ім'яjnpuzepa} [,. .п]

Приведемо приклади використання тригерів.

Приклад 6.11. Використання тригера для реалізації обмежень на значення. Наприклад інформаційна система відслідковує транзакції, що відбуваються на складі супермаркету. Кожна транзакція фіксується в таблиці Операція. Бізнес-логіка цієї операції проста: кількість проданого товару не може перевищувати залишок з таблиці Склад. Команда вставки запису в таблицю exam може бути, наприклад, такий:

INSERT INTO Операція

VALUES (3,1-299, '08/01/2009')

Створюваний тригер повинен відреагувати на її виконання таким чином: необхідно відмінній команду, якщо в таблиці Склад величина залишку товару виявилася менше кількості товару, що продавалася, з введеним кодом (у прикладі код товара=3). У записі, що вставляється, кількість товару указується із знаком «+», якщо товар поставляється, і із знаком «-», якщо він продається. Представлений тригер налаштований на обробку тільки одного запису, що додається.

CREAТЕ TRIGGER Тригер_ins

GRANT ROLE ім'я ролі [ON об'єкт] ТО суб'єкт [WITH GRANT OPTION] 195

ШВІ 208

FROM deleted 213

WHERE -inserted.KuibKicmb<=ALL(SELECT Склад.Залишок FROM Склад, Операція

WHERE Склад.КодТовара=Операція. Код Товара))

BEGIN

GRANT ROLE ім'я ролі [ON об'єкт] ТО суб'єкт [WITH GRANT OPTION] 195

ШВІ 208

FROM deleted 213

Приклад 6.12. Використання тригера для збору статистичних даних. Створити тригер для обробки операції вставки запису в таблицю Операція, наприклад, такої команди:

INSERT INTO Операція VALUES (3,1,200, '01/08/2002')

Поставляється товар з кодом 3 від клієнта з кодом 1 в кількості 200 одиниць. При продажі або отриманні товару необхідно відповідним чином змінити кількість його складського запасу. Якщо товару на складі ще немає, необхідно додати відповідний запис в таблицю Склад. Тригер обробляє тільки один рядок, що додається.

ALTER TRIGGER Тригер Jns ON Операція FOR INSERT AS

DECLARE @x INT @y INT IF @@RO WCO UNT= 1

у таблицю Операція додається запис про постачання товару BEGIN

кількість проданого товару повинна бути не менше, ніж його залишок з таблиці Склад

IF NOT EX1STS(SELECT *

FROM inserted

WHERE -inserted.Кількість< =ALL(SELECTСклад.Залишок FROM Склад, Операція WHERE Склад.КодТовара- Операція.КодТовара))

BEGIN

ROLLBACK TRAN PRINT ’відкочування товару нема '

END

Якщо запису про поставлений товар ще немає, додається відповідний запис у таблицю Склад:

IF NOT EXISTS ( SELECT *

FROM Склад C, inserted і WHERE С.КодТовара=і. КодТовара )

INSERT INTO Склад (КодТовара, Залишок)

ELSE

Якщо запис про товар вже був в таблиці Склад, то визначається код і кількість товару із доданої в таблицю Операція запису:

BEGIN

SELECT @у-і. КодТовара, @рс-і. Кількість FROM Операція С, inserted і WHERE С.КодТовара=і.КодТовара і проводить зміни кількості товару в таблиці Склад UPDATE Склад SET Залишок=Залишок+@х WHERE КодТовара=@у END END

Приклад 6.13. Створити тригер для обробки операції видалення запису з таблиці Операція, наприклад, такої команди:

DELETE FROM Операція WHERE КодУгоди=14 Для товару, код якого вказаний при видаленні запису, необхідно відкоригувати його залишок на складі. Тригер обробляє тільки один запис, що видаляється.

CREATE TRIGGER Тригер_del ON Операція FOR DELETE AS

IF @@ROWCOUNT=I - видалений один запис BEGIN DECLARE @y INT,@x 1NT

визначається код і кількість товару з видаленою з таблиці Склад запису

SELECT@у=КодТовара, @х~Кількість

FROM deleted

у таблиці Склад коригується кількість товару UPDATE Склад '

SET Залишок=Залишок-@х WHERE КодТовару-@у END '

Приклад 6.14. Створити тригер для обробки операції зміни запису в таблиці Операція, наприклад, такою командою:

UPDATE Операція SET Кількість =Кількість-І0 WHERE КодТовару=31 у всіх операціях з товаром, що має код, дорівнює 31, зменшити кількість товару на 10 одиниць. Вказана команда може привести до зміни відразу декількох записів в таблиці Операція. Тому покажемо, як створити тригер, що обробляє не один запис. Для кожного зміненого запису необхідно для старого (до зміни) коду товару зменшити залишок товару на складі на величину старої (до зміни) кількості товару і для нового (після зміни) коду товару збільшити його залишок на складі на величину нового (після зміни) значення. Щоб обробити всі змінені записи, введемо курсори, в яких збережемо всі старі (з таблиці deleted) і всі нові значення (з таблиці inserted). Ось тут нам знадобляться оператори групи Cursor Control Language (CCL), зокрема FETCH.

CREATE TRIGGER Тригер_upd ON Операція FOR UPDATE AS

DECLARE @x INT @x_old INT @y INT @y_old INT курсор з новими значеннями DECLARE CUR1 CURSOR FOR SELECT КодТовара, Кількість FROM inserted курсор із старими значеннями DECLARE CUR2 CURSOR FOR SELECT КодТовара, Кількість FROM deleted OPEN CUR1

OPEN CUR2

переміщаємося паралельно по обох курсорах FETCH NEXT FROM CUR 1 INTO @x, @y FETCH NEXT FROM CUR2 INTO @x_old, @y_old WHILE @@FETCH STATUS-0 BEGIN

для старого коду товару зменшується його кількість на складі UPDATE Склад

SET Залишок-Залишок-@у_оІс1 WHERE Код Товару=@x_old для нового коду товару, якщо такого товару ще немає на складі, вводиться новий запис

IF NOT EXISTS (SELECT * FROM Склад WHERE КодТовару=@x)

INSERT INTO Склад(КодТовара,Залишок)

VALUES (@x,@y)

I ELSE

інакше для нового коду товару збільшується його кількість на складі UPDATE Склад SET Залишок=Залишок+@у WHERE КодТовару=@х FETCH NEXT FROM CUR I INTO @x, @y FETCH NEXT FROM CUR2 INTO (cbx old, @y old

END Г , . 7/ ' Л1

CLOSE CURI

CLOSE CUR2

DEALLOCATE CURI

DEALLOCATE CUR2

У розглянутому тригері відсутнє порівняння кількості товару при зміні запису про операцію з його залишком на складі.

Приклад 6.15. Виправлення помилки. Для генерування повідомлення про помилку використовуємо в тілі тригера команду MS SQL Server RAISERROR, аргументами якої є текст повідомлення, рівень серйозності і статус помилки.

ALTER TRIGGER Тригер_upd ON Операція FOR UP DA ТЕ AS

DECLARE @x INT @x_old INT @y INT @y_old I NT, @o INT DECLARE CURI CURSOR FOR SELECT КодТовару, Кількість FROM inserted DECLARE CUR2 CURSOR FOR SELECT КодТовару, Кількість FROM deleted OPEN CURI OPEN CUR2 FETCH NEXT FROM CUR I INTO @x, @y FETCH NEXT FROM CUR2 INTO @x_old, @y_old

WHILE @@FETCH_STA TUS=0 BEGIN

SELECT @о-залишок FROM Склад WHERE кодтовара-@х IF @o<-@y BEGIN

RA ISERROR('omKam16,10)

CLOSE CUR1 CLOSE CUR2 DEALLOCATE CUR1 DEALLOCATE CUR22 ROLLBACK TRAN RETURN END UPDATE Склад SET Залиіиок~Залишок-@у_оШ WHERE KodToeapa=@x_old IF NOT EXISTS (SELECT * FROM Склад WHERE KodToeapa=@x)

INSERT INTO Склад(КодТовара, Залишок)

VALUES (@x,@y)

ELSE UPDATE Склад SET Залишок=Залишок+@у WHERE KodToeapa=@x FETCH NEXT FROM CUR1 INTO @x, @y FETCH NEXT FROM CUR2 INTO @pc_old, @y_old END

CLOSE CUR1 CLOSE CUR2 DEALLOCATE CUR1 DEALLOCATE CUR2