Триггеры SQL и когда или когда их не использовать.


43

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

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

Каково мнение сообщества в этом? Является ли это чьим-то личным предпочтением или следует избегать триггеров (точно так же, как курсоров), если для этого нет веских причин.


Ответы:


32

В статье Википедии о триггерах базы данных представлен хороший обзор того, что такое триггеры и когда их использовать в разных базах данных.

Следующее обсуждение основано только на SQL Server.

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

Триггеры дают вам контроль непосредственно перед изменением данных и сразу после их изменения. Это позволяет:

  • Аудит, как упоминалось ранее
  • Проверка и проверка безопасности бизнеса, если это желательно. Благодаря такому типу управления вы можете выполнять такие задачи, как форматирование столбцов до и после вставки в базу данных.

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

Возможно, некоторые из причин этого:

  1. Некоторые функции, которые триггеры выполняли в прежние времена, теперь могут выполняться другими способами, такими как обновление итогов и автоматический расчет по столбцу.
  2. Вы не видите, где вызывается триггер, только проверяя код, не зная, что он существует. Вы видите их эффект, когда видите изменения данных, и иногда сложно понять, почему произошло это изменение, если вы не знаете, есть ли триггер или что-то еще, действующее в таблице (ах).
  3. Если вы используете несколько элементов управления базой данных, таких как CHECK, RI, триггеры для нескольких таблиц, подробный поток вашей транзакции становится сложным для понимания и обслуживания. Вам нужно будет точно знать, что происходит, когда. Опять же, вам понадобится хорошая документация для этого.

Некоторые различия между триггерами и хранимыми процедурами без триггера (среди прочих):

  • Хранимая процедура без триггера похожа на программу, которую нужно явно вызывать либо из кода, либо из планировщика, либо из пакетного задания и т. Д., Чтобы выполнить свою работу, тогда как триггер - это специальный тип хранимой процедуры, которая запускается как ответ на событие, а не быть непосредственно выполненным пользователем. Событием может быть изменение данных в столбце данных, например.
  • Триггеры имеют типы. Триггеры DDL и триггеры DML (типов: INSTEAD OF, For и AFTER)
  • Хранимые процедуры без триггера могут ссылаться на любой тип объекта, однако для ссылки на представление необходимо использовать триггеры INSTEAD OF.
  • В SQLServer у вас может быть любое число хранимых процедур без триггера, но только 1 триггер INSTEAD OF на таблицу.

8

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

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

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

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

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

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


3

Использование триггеров базы данных

  1. Управлять значениями столбцов автоматически.
  2. Для обеспечения сложных ограничений целостности.
  3. Для соблюдения сложных бизнес-правил.
  4. Для настройки сложных авторизаций безопасности.
  5. Поддерживать дубликаты таблиц.
  6. Аудит изменения данных.

2

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

Например, я недавно работал над базой данных, которая ранее существовала исключительно как офисная система. Когда веб-приложение было написано для взаимодействия с ним, мы хотели внедрить систему уведомлений (например, подобную stackexchange), которая запускалась бы несколькими событиями, такими как обработка транзакции и т. Д. Мы смогли реализовать триггер, чтобы обновления в служебной части офиса запускали триггер, чтобы создать уведомление для веб-интерфейса и сообщить пользователю, что его транзакция была обработана офисом.


1

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


0

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

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

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

Вместо этого вы можете поместить триггер в таблицу, чтобы обновлять очередь. Гарантированно не пропустить ничего. Одно центральное расположение. Производительность снижается? Не совсем, потому что нельзя избежать попадания в очередь, будь то по триггеру или по внешнему.

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


Но есть определенно много вещей, которые НЕ должны быть реализованы с помощью триггера.
Лорд Тидус

-6

Триггер, который отправляет электронную почту, не обязательно является «глупой» идеей. Что глупо, так это не предвидеть перебои с электронной почтой в дизайне и обрабатывать их без потери данных. «Глупая» часть этого действительно плоха для несуществующей обработки ошибок ленивыми разработчиками, которые чувствуют, что они невосприимчивы к ошибкам.

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

Фанатизм действительно наносит вред.


1
Я не вижу нигде в вопросе, где упоминается слово «электронная почта». Возможно, вы пытались ответить на другой ответ? Stack Exchange - это не форум .
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.