Как запускаються Триггеры в SQL Server (операции над несколькими строками)?

DennisL
Дата: 13.03.2001 16:07:19
Интересуют следующие вопросы :
1. При каких условиях триггер не будет запущен повторно ? Как я понимаю, это происходит при изменении (добавлении, удалении) нескольких строк таблице одним оператором (UPDATE, INSERT, DELETE). При каких еще условиях это происходит (например операции в составе одной транзакции или пакета) ?
2. Как влияет на повторный запуск триггера использование пакетного обновления записей на сервере (Dataset.LockType:=ltBacthOptimistic ... в Delpi)?
3. Можно ли както добиться повторного запуска триггера на изменения(добавление, удаление) в каждой строке. Либо настройками SQL Srever или каким-то другим способом ?

все вопросы интересуют для SQL Server 7 или 2000 (если есть разница) !
Заранее спасибо за ответ !
SergSuper
Дата: 13.03.2001 16:31:06
Триггер запускается при выполнении на сервере операторов insert, delete или update. На него не влияет выполняются ли эти действия в пакете, из процедуры или из триггера других таблиц. Обновляется одна запись или несколько можно узнать внутри триггера из таблиц deleted и inserted.

Непонятно зачем добиваться повторного выполнения триггера - не проще ли все действия выполнить при первом его вызове? Но вообще если написать типа:
update TBL set FLD=FLD where ...
то триггер вызоветься и при этом никаких изменений не произойдет.

В базе настраивается будет ли триггер вызываться рекурсивно. Но это действует сразу для всех триггеров базы.

А вообще я не очень понял что вы имеете ввиду под "повторным запуском триггера "
Genady
Дата: 13.03.2001 16:33:00
Триггер MS SQL всегда запускается один раз, поэтому при написании триггера это нужно учитывать и работать не с одной строкой а набором строк.

Чтобы повторно запустить триггер нужно повторно сделать операцию insert update delete

Советую почитать BOL для лучшего понимания механизма работы триггеров.
Garya
Дата: 13.03.2001 19:48:00
Судя по всему, ранее DennisL работал с СУБД, в которой присутствуют триггеры BEFORE и AFTER. Как правило, в таких инструментариях триггеры срабатывают на операцию с каждой строкой таблицы по отдельности. В MS SQL Server есть только After-триггеры (даже Instead-триггеры SQL-2000 по своей сути являются AFTER-триггерами). Когда триггер сработал, операция УЖЕ ПРОИЗОШЛА, причем над всем массивом записей. Однако, ее еще можно откатить, либо внести в результаты ее работы некоторые изменения, либо дополнительные действия. Что именно произошло во время операции, можно узнать из специальных таблиц Deleted и Inserted. Грамотно построенный триггер в MS SQL SERVER не должен предполагать действий только над одной строкой (хотя, конкретное клиентское приложение, возможно, производит только построчные операции с таблицей). Он должен уметь обработать ситуацию, когда вызвана операция над пустым множеством строк, а также когда строк больше одной - на случай, если такие операции запущены из EM, QA или вообще из космоса...
Павел
Дата: 14.03.2001 07:57:04
Как мне кажется, Garya сделал правильное предположение. Тоько не Иуащку и After, а Row-level и Statement-level триггеры. Когда я начал изучать MsSQL, уже был опыт работы с Sybase SA. Там все это реализовано. По началу было как-то непонятно, но быстро пришло понимание, что достаточно организовать цикл по таблицам Inserted или Deleted, чтобы получить возможность работы с отдельнвми строками, когда это необходимо.
Павел
Дата: 14.03.2001 07:57:41
Как мне кажется, Garya сделал правильное предположение. Тоько не Before и After, а Row-level и Statement-level триггеры. Когда я начал изучать MsSQL, уже был опыт работы с Sybase SA. Там все это реализовано. По началу было как-то непонятно, но быстро пришло понимание, что достаточно организовать цикл по таблицам Inserted или Deleted, чтобы получить возможность работы с отдельнвми строками, когда это необходимо.
DennisL
Дата: 14.03.2001 15:54:47
У меня (упрощенно) такая задача :

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

В принципе такую проверку хотелось бы реализовать не очень сложным способом, при изменении или удалении записи запускаеться соответствующий триггер и проверяет статус у договора если стстус не позволяет изменений и удалений то они отменяються. Вот я и хотел уточнить что будет при пакетных изменениях (они могут затронуть одновременно как счета кторые можно изменять так и счета которые нельзя отменять) ... Тут ROLLBACK TRANSACTION отменит все изменения и те что надо отменить и те что не конфликуют со статусом договора.

Вот такой пример, но у меня есть несколько схожих ситуаций .... Потому интересуютвозможные пути и приемы разрешения таких задач.
Genady
Дата: 14.03.2001 16:17:25
Посмотрите в BOL Conditional Insert Trigger.
В принципе Вы можете не откатывать транзакцию, а востановить по заданному условию записи из таблицы deleted.
Genady
Дата: 14.03.2001 16:22:16
На вский случай поясню - в момент обновления Вы получаете к Вашей обновленной таблице несколько виртуальных.
deleted - Содержит старые или удаленные записи
inserted содержит новые или обновляемые данные.

Таким образом у Вас есть возможность запрограммировать поведение триггера как Вам нужно, а откат транзакции лишь вариант такого поведения
DennisL
Дата: 14.03.2001 17:33:21
Спасибо за совет в принципе я таким способом и думал решать эту задачу просто хотелось, узнать можеь есть решения по проще, чтобы не востанавливать записи из виртуальных таблиц т.д. Дело в том что у меня опять же при внесении новой записи в таблицу производиться еще фиксацие различных бугалтерских данных в специальные таблицы и т.д. Но в принципе эта проблема разрешима, как я понял из придыдущих ответов можно запретить запуск одних тригеров из других ...