Триггер (базы данных). Что такое триггер в sql


SQL.RU | Триггеры и порядок их выполнения

До версии SQL Server 7.0, мы могли создать только три триггера на одной таблице, один INSERT, один UPDATE и один DELETE. Ситуация изменилась с выходом SQL Server 7.0. Теперь мы можем на одну таблицу задать большое количество (Ограничено числом объектов в базе данных) триггеров каждого типа.

Порядок запуска триггеров при этом никак не определен и не гарантирован. В SQL Server 2000 появилась документированная процедура sp_settriggerorder, которая позволяет изменять порядок запуска триггеров. Она позволяет указать какие триггеры AFTER срабатывают первыми или последними. Триггеры AFTER, срабатывающие между первым и последним триггерами, выполняются в неопределенном порядке.

Для демонстрации запустим скрипт:

--Тестовая таблица if object_id( 'dbo.TestTable', 'U' ) is not null drop table dbo.TestTable go create table dbo.TestTable ( id int identity, val varchar(64) ) go --Триггер 1 if object_id ( 'dbo.TestTrigger01', 'TR' ) is not null drop trigger dbo.TestTrigger01 go create trigger dbo.TestTrigger01 on dbo.TestTable for insert as if @@nestlevel > 1 return insert into dbo.TestTable values ( object_name( @@procid ) ) go --Триггер 2 if object_id ( 'dbo.TestTrigger02', 'TR' ) is not null drop trigger dbo.TestTrigger02 go create trigger dbo.TestTrigger02 on dbo.TestTable for insert as if @@nestlevel > 1 return insert into dbo.TestTable values ( object_name( @@procid ) ) go --Триггер 3 if object_id ( 'dbo.TestTrigger03', 'TR' ) is not null drop trigger dbo.TestTrigger03 go create trigger dbo.TestTrigger03 on dbo.TestTable for insert as if @@nestlevel > 1 return insert into dbo.TestTable values ( object_name( @@procid ) ) go --Триггер 4 if object_id ( 'dbo.TestTrigger04', 'TR' ) is not null drop trigger dbo.TestTrigger04 go create trigger dbo.TestTrigger04 on dbo.TestTable for insert as if @@nestlevel > 1 return insert into dbo.TestTable values ( object_name( @@procid ) ) go --Триггер 5 if object_id ( 'dbo.TestTrigger05', 'TR' ) is not null drop trigger dbo.TestTrigger05 go create trigger dbo.TestTrigger05 on dbo.TestTable for insert as if @@nestlevel > 1 return insert into dbo.TestTable values ( object_name( @@procid ) ) go Мы создали тестовую таблицу с 5-ю триггерами AFTER на событие INSERT. Каждый из триггеров добавляет запись в эту же таблицу. Теперь проведем 1ый тест, выполнив следующий скрипт: --Тест 1: Порядок запуска триггеров не задан insert into dbo.TestTable select 'Test1' go select * from dbo.TestTable order by id go

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

--Тест 2: Порядок запуска триггеров не задан, триггер №2 пересоздадим, чтобы он стал самым поздним по времени создания --Триггер 2 if object_id ( 'dbo.TestTrigger02', 'TR' ) is not null drop trigger dbo.TestTrigger02 go create trigger dbo.TestTrigger02 on dbo.TestTable for insert as if @@nestlevel > 1 return insert into dbo.TestTable values ( object_name( @@procid ) ) go insert into dbo.TestTable select 'Test2' go select * from dbo.TestTable order by id go

Теория подтвердилась, но это всего лишь совпадение, и такое поведение не гарантировано и, как указано в БОЛ, без явного указания порядка, триггеры выполняются случайным образом. Но через процедуру sp_settriggerorder мы можем задать только триггеры AFTER, срабатывающие первыми или последними. Триггеры AFTER, срабатывающие между первым и последним триггерами, выполняются в неопределенном порядке. Т.е. если у нас 3 триггера на одно событие, то мы сможем гарантировать порядок срабатывания, через эту процедуру. Но если триггеров больше, как в нашем случае, то порядок будет гарантирован только для первого и последнего триггера. Для иллюстрации работы процедуры sp_settriggerorder, укажем в качестве первого триггера Триггер 2, а последним Триггер 3:

--Тест 3: Зададим порядок запуска триггеров 2 и 3 exec sp_settriggerorder 'dbo.TestTrigger02', 'first', 'insert' go exec sp_settriggerorder 'dbo.TestTrigger03', 'last', 'insert' go insert into dbo.TestTable select 'Test3' go select * from dbo.TestTable order by id go

При попытке задать для другого триггера порядок выполнения, например первым (first), мы получим ошибку: Msg 15130, Level 16, State 1, Procedure sp_settriggerorder, Line 163 There already exists a 'first' trigger for 'insert'.

Просмотреть, задан ли порядок запуска для триггера можно с помощью функции OBJECTPROPERTY

select name , objectproperty( object_id, 'ExecIsFirstInsertTrigger') FirstInsertTrigger , objectproperty( object_id, 'ExecIsLastInsertTrigger') LastInsertTrigger from sys.triggers where name like 'TestTrigger0%'

На что ещё стоит обратить внимание: Если один и тот же триггер необходимо назначить в качестве первого или последнего для нескольких типов инструкций, процедуру sp_settriggerorder необходимо выполнить для каждого типа инструкций. Кроме того, прежде чем триггер может быть назначен в качестве первого (First) или последнего (Last) выполняющегося триггера для того или иного типа инструкций, этот триггер должен быть сначала определен для данного типа.

Ну и последний тест, сбросим порядок запуска триггеров 2 и 3:

--Тест 4: Сбросим порядок запуска триггеров 2 и 3 exec sp_settriggerorder 'dbo.TestTrigger02', 'none', 'insert' go exec sp_settriggerorder 'dbo.TestTrigger03', 'none', 'insert' go insert into dbo.TestTable select 'Test4' go select * from dbo.TestTable order by id go

Триггеры были запущены в том же порядке, что и до явного выставления порядка у триггеров 2 и 3.

www.t-sql.ru

Типы триггеров

В SQL Server существует два параметра, определяющих поведение триггеров:

  • AFTER. Триггер выполняется после успешного выполнения вызвавших его команд. Если же команды по какой-либо причине не могут быть успешно завершены, триггер не выполняется. Следует отметить, что изменения данных в результате выполнения запроса пользователя и выполнение триггера осуществляется в теле одной транзакции: если произойдет откат триггера, то будут отклонены и пользовательские изменения. Можно определить несколько AFTER-триггеров для каждой операции (INSERT, UPDATE, DELETE). Если для таблицы предусмотрено выполнение нескольких AFTER-триггеров, то с помощью системной хранимой процедуры sp_settriggerorder можно указать, какой из них будет выполняться первым, а какой последним. По умолчанию в SQL Server все триггеры являются AFTER-триггерами.

  • INSTEAD OF. Триггер вызывается вместо выполнения команд. В отличие от AFTER-триггера INSTEAD OF-триггер может быть определен как для таблицы, так и для просмотра. Для каждой операции INSERT, UPDATE, DELETE можно определить только один INSTEAD OF-триггер.

Триггеры различают по типу команд, на которые они реагируют.

Существует три типа триггеров:

  • INSERT TRIGGER – запускаются при попытке вставки данных с помощью команды INSERT.

  • UPDATE TRIGGER – запускаются при попытке изменения данных с помощью команды UPDATE.

  • DELETE TRIGGER – запускаются при попытке удаления данных с помощью команды DELETE.

Конструкции [ DELETE] [,] [ INSERT] [,] [ UPDATE] и FOR | AFTER | INSTEAD OF } { [INSERT] [,] [UPDATE] определяют, на какую команду будет реагировать триггер. При его создании должна быть указана хотя бы одна команда. Допускается создание триггера, реагирующего на две или на все три команды.

Аргумент WITH APPEND позволяет создавать несколько триггеров каждого типа.

При создании триггера с аргументом NOT FOR REPLICATION запрещается его запуск во время выполнения модификации таблиц механизмами репликации.

Конструкция AS sql_оператор[...n] определяет набор SQL- операторов и команд, которые будут выполнены при запуске триггера.

Отметим, что внутри триггера не допускается выполнение ряда операций, таких, например, как:

  • создание, изменение и удаление базы данных;

  • восстановление резервной копии базы данных или журнала транзакций.

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

программирование триггера

При выполнении команд добавления, изменения и удаления записей сервер создает две специальные таблицы: inserted и deleted. В них содержатся списки строк, которые будут вставлены или удалены по завершении транзакции. Структура таблиц inserted и deleted идентична структуре таблиц, для которой определяется триггер. Для каждого триггера создается свой комплект таблиц inserted и deleted, поэтому никакой другой триггер не сможет получить к ним доступ. В зависимости от типа операции, вызвавшей выполнение триггера, содержимое таблиц inserted и deleted может быть разным:

  • команда INSERT – в таблице inserted содержатся все строки, которые пользователь пытается вставить в таблицу; в таблице deleted не будет ни одной строки; после завершения триггера все строки из таблицы inserted переместятся в исходную таблицу;

  • команда DELETE – в таблице deleted будут содержаться все строки, которые пользователь попытается удалить; триггер может проверить каждую строку и определить, разрешено ли ее удаление; в таблице inserted не окажется ни одной строки;

  • команда UPDATE – при ее выполнении в таблице deleted находятся старые значения строк, которые будут удалены при успешном завершении триггера. Новые значения строк содержатся в таблице inserted. Эти строки добавятся в исходную таблицу после успешного выполнения триггера.

Для удаления триггера используется команда

DROP TRIGGER {имя_триггера} [,...n]

  1. Т-SQL. Ссылочная целостность. Правила ссылочной целостности и поддержка их с помощью триггеров. Примеры.

При создании баз данных большое внимание должно быть уделено средствам поддержания данных в целостном состоянии. Рассмотрим предусмотренные стандартом языка SQL функции, которые предназначены для поддержания целостности данных. Эта поддержка включает средства задания ограничений, они вводятся с целью защиты базы данных от нарушения согласованности сохраняемых в ней данных. К таким типам поддержки целостности данных относятся:

  • обязательные данные;

  • ограничения для доменов полей;

  • целостность сущностей;

  • ссылочная целостность;

  • требования конкретного предприятия.

studfiles.net

Триггер (базы данных) - это... Что такое Триггер (базы данных)?

Три́ггер (англ. trigger) — это хранимая процедура особого типа, которую пользователь не вызывает непосредственно, а исполнение которой обусловлено действием по модификации данных: добавлением INSERT, удалением DELETE строки в заданной таблице, или изменением UPDATE данных в определенном столбце заданной таблицы реляционной базы данных. Триггеры применяются для обеспечения целостности данных и реализации сложной бизнес-логики. Триггер запускается сервером автоматически при попытке изменения данных в таблице, с которой он связан. Все производимые им модификации данных рассматриваются как выполняемые в транзакции, в которой выполнено действие, вызвавшее срабатывание триггера. Соответственно, в случае обнаружения ошибки или нарушения целостности данных может произойти откат этой транзакции.

Момент запуска триггера определяется с помощью ключевых слов BEFORE (триггер запускается до выполнения связанного с ним события; например, до добавления записи) или AFTER (после события). В случае, если триггер вызывается до события, он может внести изменения в модифицируемую событием запись (конечно, при условии, что событие — не удаление записи). Некоторые СУБД накладывают ограничения на операторы, которые могут быть использованы в триггере (например, может быть запрещено вносить изменения в таблицу, на которой «висит» триггер, и т. п.)

Кроме того, триггеры могут быть привязаны не к таблице, а к представлению (VIEW). В этом случае с их помощью реализуется механизм «обновляемого представления». В этом случае ключевые слова BEFORE и AFTER влияют лишь на последовательность вызова триггеров, так как собственно событие (удаление, вставка или обновление) не происходит.

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

Пример (Oracle):

/* Триггер на уровне таблицы */ CREATE OR REPLACE TRIGGER DistrictUpdatedTrigger AFTER UPDATE ON district BEGIN INSERT INTO info VALUES ('table "district" has changed'); END;

В этом случае для отличия табличных триггеров от строчных вводится дополнительные ключевые слова при описании строчных триггеров. В Oracle это словосочетание FOR EACH ROW.

Пример:

/* Триггер на уровне строки */ CREATE OR REPLACE TRIGGER DistrictUpdatedTrigger AFTER UPDATE ON district FOR EACH ROW BEGIN INSERT INTO info VALUES ('one string in table "district" has changed'); END;

xzsad.academic.ru

Триггер (базы данных) - это... Что такое Триггер (базы данных)?

Три́ггер (англ. trigger) — это хранимая процедура особого типа, которую пользователь не вызывает непосредственно, а исполнение которой обусловлено действием по модификации данных: добавлением INSERT, удалением DELETE строки в заданной таблице, или изменением UPDATE данных в определенном столбце заданной таблицы реляционной базы данных. Триггеры применяются для обеспечения целостности данных и реализации сложной бизнес-логики. Триггер запускается сервером автоматически при попытке изменения данных в таблице, с которой он связан. Все производимые им модификации данных рассматриваются как выполняемые в транзакции, в которой выполнено действие, вызвавшее срабатывание триггера. Соответственно, в случае обнаружения ошибки или нарушения целостности данных может произойти откат этой транзакции.

Момент запуска триггера определяется с помощью ключевых слов BEFORE (триггер запускается до выполнения связанного с ним события; например, до добавления записи) или AFTER (после события). В случае, если триггер вызывается до события, он может внести изменения в модифицируемую событием запись (конечно, при условии, что событие — не удаление записи). Некоторые СУБД накладывают ограничения на операторы, которые могут быть использованы в триггере (например, может быть запрещено вносить изменения в таблицу, на которой «висит» триггер, и т. п.)

Кроме того, триггеры могут быть привязаны не к таблице, а к представлению (VIEW). В этом случае с их помощью реализуется механизм «обновляемого представления». В этом случае ключевые слова BEFORE и AFTER влияют лишь на последовательность вызова триггеров, так как собственно событие (удаление, вставка или обновление) не происходит.

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

Пример (Oracle):

/* Триггер на уровне таблицы */ CREATE OR REPLACE TRIGGER DistrictUpdatedTrigger AFTER UPDATE ON district BEGIN INSERT INTO info VALUES ('table "district" has changed'); END;

В этом случае для отличия табличных триггеров от строчных вводится дополнительные ключевые слова при описании строчных триггеров. В Oracle это словосочетание FOR EACH ROW.

Пример:

/* Триггер на уровне строки */ CREATE OR REPLACE TRIGGER DistrictUpdatedTrigger AFTER UPDATE ON district FOR EACH ROW BEGIN INSERT INTO info VALUES ('one string in table "district" has changed'); END;

dic.academic.ru

sql-server - Триггеры базы данных

Подумайте о базе данных как о большом большом объекте - после каждого обращения к ней она должна находиться в логически согласованном состоянии.

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

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

Как контрапункт, позволяющий доступ к базе данных только через хранимые процедуры и представления по-прежнему позволяет доступ к бэкдорам разрешений. Пользователям с достаточными полномочиями доверяют не нарушать целостность базы данных, а все остальные используют хранимые процедуры.

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

Сложение содержимого в одной хранимой процедуре в порядке, но что происходит, когда что-то идет не так? Скажем, у вас есть 5 шагов, и первый шаг не удается, что происходит с другими шагами? Вам нужно добавить целую кучу логики, чтобы удовлетворить эту ситуацию. Когда вы начнете делать это, вы потеряете преимущества хранимой процедуры в этом сценарии.

Бизнес-логика должна идти куда-то, и существует множество подразумеваемых правил домена, встроенных в дизайн базы данных - отношения, ограничения и т.д. - это попытка кодирования бизнес-правил, говоря, например, что пользователь может иметь только один пароль. Учитывая, что вы начали перетаскивать бизнес-правила на сервер базы данных, имея эти отношения и т.д., Где вы рисуете линию? Когда база данных отказывается от ответственности за целостность данных и начинает доверять вызывающим приложениям и пользователям базы данных, чтобы понять это правильно? Хранимые процедуры с этими встроенными в них правилами могут подтолкнуть большую политическую власть в руки администраторов баз данных. Это сводится к тому, сколько уровней будет существовать в вашей n-уровневой архитектуре; если есть презентация, бизнес и уровень данных, где лежит разделение между бизнесом и данными? Что добавляет значение бизнес-уровня? Будете ли вы запускать бизнес-уровень на сервере базы данных в качестве хранимых процедур?

Да, я думаю, что необходимость обхода триггера означает, что вы "делаете это неправильно"; в этом случае триггер не для вас.

qaru.site