Взаємодія тригерів

За відсутності чіткого плану база даних, що використовує безліч тригерів, може швидко стати некерованою, і дозволити такі проблеми буде досить складно

Організація тригерів

У версії SQL Server 65 кожна подія могло мати тільки один тригер, а один тригер міг застосовуватися тільки до одного події Стиль програмування, зобовязуючий використовувати тільки такі обмежені тригери, показав свою неспроможність У версії 70 SQL Server реалізована можливість існування безлічі тригерів AFTER для однієї події таблиці, при цьому один тригер може застосовуватися до кількох подіям Це дозволило використовувати більш гнучкий стиль розробки додатків

Взявши участь у розробці баз даних, що містять сотні тригерів, я б порекомендував організовувати тригери не по подіям таблиць, а за завданнями, виконуваних тригерами, наприклад:

т■ зміна дати

■ перевірка даних

■ підтримка складних правил бізнес-логіки ■ забезпечення складної захисту даних

■ ведення журналу аудиту

Вкладені тригери

Термін вкладення тригерів вказує на те, чи можуть тригери, що викликаються інструкціями DML, викликати інші тригери Наприклад, якщо параметр сервера Nested Triggers включений і деякий тригер оновлює таблицю А, а ця таблиця сама має тригер, то і він теж буде викликаний (рис 232)

За замовчуванням параметр Nested Triggers включений Включити його явним чином можна за допомогою наступних команд:

Ехес sp_configure Nested Triggers, 1 Reconfigure

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

Тригери в SQL Server обмежені 32 рівнями рекурсії З міркувань безпеки рекомендується перевіряти поточний рівень рекурсії в самому триггере – для цього призначена функція Trigger_NestLevel () Коли межа буде досягнута, SQL Server генерує фатальну помилку

Рекурсивні тригери

Рис 233 Рекурсивний тригер ссьтается сам на себе Він виконує інструкцію DML, яка запускає його повторно

Рекурсивний тригер є унікальним типом вкладеного тригера AFTER Якщо тригер виконує інструкцію DML, яка знову викликає його самого, він називається рекурсивним (рис 233) Якщо параметр бази даних Recursive_Triggers відключений, то рекурсивна ітерація тригерів стає неможливою

Рис 232 Параметр конфігурації Nested Triggers дозволяє інструкції DML в тілі тригера ініціювати ще один тригер

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

Рекурсивні тригери включаються за допомогою інструкції ALTER DTATBASE:

ALTER DATABASE імя_бази_данних SET RECURSIVE_TRIGGERS ON | OFF

Як приклад корисного рекурсивного тригера розглянемо тригер Modif iedData Він записує поточні дату і час в змінюваний стовпець оновлюваної рядка Використовуючи навчальну базу даних OBXKites в якості моделі, додамо в таблицю товарів стовпці Created і Modified:

USE OBXKites ALTER TABLE dboProduct ADD

Created DateTime Not Null DEFAULT GetDate(),

Modified DateTime Not Null DEFAULT GetDateO

Представлений тригер спочатку виводить свій рівень вкладеності, використовуючи функцію TriggerNest () Це дуже корисно в цілях налагодження у вкладених або рекурсивних триггерах Перший оператор if оберігає стовпці Created і Modified від ручного зміни користувачем Якщо тригер ініціюється користувачем, рівень вкладеності буде дорівнювати одиниці

Перший раз тригер ініціюється інструкцією UPDATE Усі наступні запуски тригера завершуються оператором Return, оскільки рівень вкладеності перевищує одиницю Це дозволяє уникнути нескінченної рекурсії Нижче приведений код DDL цього тригера CREATE TRIGGER Products_ModifiedDate ON dboProduct FOR UPDATE AS

SET NoCount ON

PRINT Trigger_NestLevel()

If Trigger_NestLevel() &gt 1 Return

If (Update(Created) or Update(Modified))

AND Trigger_NestLevel() =1 Begin

Raiserror(1 Оновлення відключено1, 16, 1)

Rollback

Return

End

– Оновлення дати зміни рядка UPDATE Product

SET Modified = getdate()

FROM Product JOIN Inserted

ON ProductProductID = InsertedProductID

Для тестування тригера виконаємо наступну інструкцію UPDATE, що призведе до зміни тригером значення стовпця Modified Після цього інструкція SELECT повертає дату і час з стовпців Created і Modified:

UPDATE PRODUCT

SET [Name] = Modified Trigger

WHERE Code = 1002

SELECT Code, Created, Modified

FROM Product

WHERE Code = 1002

Буде отримано наступний результат:

Code Created                                       Modified

1002&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp 2002-02-18 09:48:31700 2002-02-18 15:19:34350

Рекурсивні тригери необхідні в репліцируємих базах даних

На замітку

Тригери INSTEAD OF І AFTER

Якщо таблиця для одного і того ж події має тригери INSTEAD OF і AFTER, можлива наступна послідовність операцій

1&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp Інструкція DML ініціює транзакцію

2&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp Замість інструкції DML виконується тригер INSTEAD OF

3&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp Якщо тригер INSTEAD OF виконує інструкцію DML для того ж події таблиці, то процес триває

4&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp Виконується тригер AFTER

Безліч тригерів after

Якщо деяка подія таблиці має кілька тригерів AFTER, то всі вони будуть виконані Порядок виконання цих тригерів менш важливий, ніж може здатися на перший погляд

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

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

Для завдання порядку випоненія тригерів використовується системна збережена процедура sp_settriggerorder Вони має наступний синтаксис:

sp_settriggerorder

@ Triggername = імя_тріггера1,

@ Order = first або last або none,

@ Stmttype = INSERT або UPDATE або DELETE

Ефект від установки порядку тригерів не має властивість кумулятивности Наприклад, якщо встановити тригер А першим, а потім встановити тригер Б першим, це не відсуне тригер А на друге місце У даному випадку він повернеться в невпорядковане стан

Резюме

Тригери є ключовою функцією в базах даних з архітектурою клієнт / сервер, дозволяють розробнику створювати складні правила бізнес-логіки і гарантувати їх суворе виконання на рівні бази даних SQL Server 2005 містить два типи тригерів: AFTER і INSTEAD OF

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

Джерело: Нільсен, Пол Microsoft SQL Server 2005 Біблія користувача : Пер з англ – М: ООО ІД Вільямс , 2008 – 1232 с : Ил – Парал тит англ

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*