Раньше я никогда не был поклонником использования триггеров для таблиц базы данных. Для меня они всегда представляли некую «магию», которая должна была произойти на стороне базы данных, вдали от контроля моего кода приложения. Я также хотел ограничить объем работы, которую должна была выполнять БД, поскольку это обычно общий ресурс, и я всегда предполагал, что триггеры могут быть дорогими в сценариях с высокой нагрузкой.
Тем не менее, я нашел пару случаев, когда было целесообразно использовать триггеры (по крайней мере, на мой взгляд, они имели смысл). Однако недавно я оказался в ситуации, когда мне иногда нужно было «обойти» триггер. Я чувствовал себя действительно виноватым из-за того, что мне пришлось искать способы сделать это, и я все еще думаю, что лучший дизайн базы данных устранит необходимость в этом обходе. К сожалению, эта БД используется несколькими приложениями, некоторые из которых поддерживаются очень недружелюбной командой разработчиков, которая кричала бы об изменениях схемы, так что я застрял.
Каковы общие мнения о триггерах? Любите их? Ненавижу их? Думаете, они служат определенной цели в некоторых сценариях? Считаете ли вы, что необходимость обойти триггер означает, что вы «делаете это неправильно»?





Я работаю с веб-приложениями и приложениями winforms на C# и с энтузиазмом использую триггеры НЕНАВИДЕТЬ. Я никогда не сталкивался с ситуацией, когда я мог бы оправдать использование триггера перемещением этой логики на бизнес-уровень приложения и репликацией там логики триггера.
Я не занимаюсь какой-либо работой с типом DTS или чем-то подобным, поэтому могут быть некоторые варианты использования триггера там, но если кто-то в любой из моих команд скажет, что они могут захотеть использовать триггер, им лучше подготовить свои аргументы потому что я отказываюсь стоять в стороне и позволяю добавлять триггеры в любую базу данных, над которой я работаю.
Некоторые причины, по которым мне не нравятся триггеры:
Я уверен, что могу придумать и другие причины, но только их достаточно, чтобы я не использовал триггеры.
Лично я не фанат. Я буду использовать их, но только когда обнаружу узкое место в коде, которое можно устранить, переместив действия в триггер. Как правило, я предпочитаю простоту, и один из способов сохранить простоту - хранить логику в одном месте - в приложении. Я также работал на рабочих местах, где доступ очень разрознен. В таких средах, чем больше кода я упаковываю, тем больше людей мне нужно привлекать даже для самых простых исправлений.
Я обнаруживаю, что обхожу триггеры при массовом импорте данных. Считаю это оправданным в таких обстоятельствах.
Если вы в конечном итоге очень часто обходите триггеры, вам, вероятно, нужно еще раз взглянуть на то, для чего вы их вставляете в первую очередь.
В общем, я бы проголосовал за «в некоторых сценариях они служат определенной цели». Я всегда нервничаю по поводу последствий для производительности.
Триггеры могут быть очень полезными. Они также могут быть очень опасными. Я думаю, что они подходят для задач по уборке дома, таких как заполнение данных аудита (созданных, измененной даты и т. д.), А в некоторых базах данных могут использоваться для ссылочной целостности.
Но я не большой поклонник добавления в них большого количества бизнес-логики. Это может сделать поддержку проблематичной, потому что:
Что касается необходимости обхода триггера, чтобы что-то сделать, это может означать, что вы делаете что-то не так, или это может означать, что триггер делает что-то не так.
Общее правило, которое я использую для триггеров, - делать их легкими, быстрыми, простыми и максимально неинвазивными.
Я впервые использовал триггеры пару недель назад. Мы перешли на производственный сервер с SQL 2000 на SQL 2005 и обнаружили, что драйверы по-разному ведут себя с полями NText (сохраняя большой XML-документ), отбрасывая последний байт. Я использовал триггер в качестве временного исправления, чтобы добавить дополнительный фиктивный байт (пробел) в конец данных, решая нашу проблему до тех пор, пока не будет найдено правильное решение.
Помимо этого специального временного случая, я бы сказал, что я бы избегал их, поскольку они действительно скрывают то, что происходит, и функция, которую они предоставляют, должна обрабатываться разработчиком явно, а не как некая скрытая магия.
Думайте о базе данных как о большом большом объекте - после каждого обращения к нему он должен находиться в логически непротиворечивом состоянии.
Базы данных открываются через таблицы, а поддержание согласованности таблиц и строк может быть выполнено с помощью триггеров. Другой способ сохранить их согласованность - запретить прямой доступ к таблицам и разрешить его только через хранимые процедуры и представления.
Обратной стороной триггеров является то, что их может вызывать любое действие; это тоже сила - никто не собирается портить целостность системы своей некомпетентностью.
В противоположность этому, разрешение доступа к базе данных только через хранимые процедуры и представления по-прежнему разрешает доступ через бэкдор к разрешениям. Пользователям с достаточными разрешениями доверяют, что они не нарушат целостность базы данных, все остальные используют хранимые процедуры.
Что касается сокращения объема работы: базы данных потрясающе эффективны, когда им не приходится иметь дело с внешним миром; вы будете действительно удивлены, насколько даже переключение процессов вредит производительности. Это еще один положительный момент хранимых процедур: вместо дюжины обращений к базе данных (и всех связанных циклических обращений) есть один.
Bunching stuff up in a single stored proc is fine, but what happens when something goes wrong? Say you have 5 steps and the first step fails, what happens to the other steps? You need to add a whole bunch of logic in there to cater for that situation. Once you start doing that you lose the benefits of the stored procedure in that scenario.
Бизнес-логика должна куда-то идти, и в структуру базы данных встроено множество подразумеваемых доменных правил - отношения, ограничения и так далее - это попытка кодифицировать бизнес-правила, например, говоря, что у пользователя может быть только один пароль. Учитывая, что вы начали переносить бизнес-правила на сервер базы данных, установив эти отношения и т. д., Где вы проводите черту? Когда база данных откажется от ответственности за целостность данных и начнет доверять вызывающим приложениям и пользователям базы данных, чтобы все исправить? Хранимые процедуры с этими встроенными в них правилами могут передать большую политическую власть в руки администраторов баз данных. Все сводится к тому, сколько уровней будет существовать в вашей n-уровневой архитектуре; если есть уровень представления, бизнеса и данных, в чем заключается разделение между бизнесом и данными? Какие преимущества добавляет бизнес-уровень? Будете ли вы запускать бизнес-уровень на сервере базы данных как хранимые процедуры?
Да, я думаю, что необходимость обходить триггер означает, что вы «делаете это неправильно»; в этом случае триггер не для вас.

Честно говоря, это единственный раз, когда я использую триггеры для имитации уникального индекса, которому разрешено иметь NULL, что не учитывается в уникальности.
As to reducing the amount of work: databases are stunningly efficient when they don't have to deal with the outside world; you'd be really surprised how much even process switching hurts performance. That's another upside of stored procedures: rather than a dozen calls to the database (and all the associated round trips), there's one.
это немного не по теме, но вы также должны знать, что вы смотрите на это только с одного потенциального положительного момента.
Сгруппировать данные в одной сохраненной процедуре - это нормально, но что произойдет, если что-то пойдет не так? Допустим, у вас есть 5 шагов, и первый шаг не удался, что происходит с другими шагами? Вам нужно добавить туда целую кучу логики, чтобы учесть эту ситуацию. Как только вы начнете это делать, вы потеряете все преимущества хранимой процедуры в этом сценарии.
Общий вентилятор,
но на самом деле нужно использовать его экономно, когда,
Необходимо поддерживать согласованность (особенно, когда таблицы измерений используются на складе, и нам нужно связать данные в таблице фактов с их правильным измерением. Иногда правильная строка в таблице измерений может быть очень дорогостоящей для вычисления, поэтому вам нужен ключ Чтобы быть записанным прямо в таблицу фактов, один хороший способ поддерживать эту «связь» - использовать триггер.
Необходимо регистрировать изменения (например, в таблице аудита полезно знать, какой пользователь @@ сделал изменение и когда оно произошло)
Некоторые СУБД, такие как sql server 2005, также предоставляют вам триггеры для операторов CREATE / ALTER / DROP (чтобы вы могли знать, кто создал какую таблицу, когда, какой столбец, когда и т. д.)
Честно говоря, используя триггеры в этих трех сценариях, я не понимаю, зачем вам вообще нужно их «отключать».
Триггеры обычно используются неправильно, вносят ошибки, поэтому их следует избегать. Никогда не создавайте триггер для проверки ограничений целостности, пересекающий строки в таблице (например, «средняя зарплата по отделам не может превышать X»).
Том Кайт, вице-президент Oracle, указал, что он предпочел бы базу данных удалить триггеры как функцию Oracle из-за их частой роли в ошибках. Он знает, что это всего лишь мечта, и триггеры здесь, чтобы остаться, но если бы он мог, он бы удалил триггеры из Oracle, он бы это сделал (вместе с предложением WHEN OTHERS и автономными транзакциями).
Can triggers be used correctly? Absolutely.
The problem is - they are not used correctly in so many cases that I'd be willing to give up any perceived benefit just to get rid of the abuses (and bugs) caused by them. - Tom Kyte
Общее практическое правило: не используйте триггеры. Как упоминалось ранее, они добавляют накладные расходы и сложность, которых можно легко избежать, переместив логику с уровня БД.
Кроме того, в MS SQL Server триггеры запускаются один раз для каждой команды sql, а не для каждой строки. Например, следующий оператор sql выполнит триггер только один раз.
UPDATE tblUsers
SET Age = 11
WHERE State = 'NY'
Многие, в том числе и я, думали, что триггеры срабатывают для каждой строки, но это не так. Если у вас есть оператор sql, подобный приведенному выше, который может изменять данные более чем в одной строке, вы можете включить курсор для обновления всех записей, затронутых триггером. Вы видите, как это можно очень быстро запутать.
Никогда не используйте курсор в триггере. Да, вам нужно учитывать множественные вставки, обновления или удаления строк, но вам нужно делать это на основе набора. Я удалил курсор из триггера, над которым работаю, и вставка 40 000 записей изменилась с 45 минут до примерно 30 секунд.
«Никогда не создавайте триггер для проверки ограничений целостности, пересекающих строки в таблице» - я не могу согласиться. Вопрос помечен как «SQL Server», и предложения CHECK constraints в SQL Server не могут содержать подзапрос; Хуже того, реализация, похоже, имеет «жестко закодированное» предположение, что CHECK будет включать только одну строку, поэтому использование функции ненадежно. Итак, если мне нужно ограничение, которое на законных основаниях включает более одной строки - и хорошим примером здесь является упорядоченный первичный ключ в классической временной таблице `` действительное время '', где мне нужно предотвратить перекрытие периодов для одного и того же объекта - как можно Я делаю это без триггера? Помните, что это первичный ключ, что-то, что нужно для обеспечения целостности данных, поэтому принудительное его применение где-либо еще, кроме СУБД, не может быть и речи. Пока ограничения CHECK не получат подзапросы, я не вижу альтернативы использованию триггеров для определенных видов ограничений целостности.
Я использую триггеры в условных выражениях вставки / обновления / удаления для увеличения / уменьшения счетчиков в таблице. Прямо сейчас это единственный раз, когда я его использую. Эти триггеры в порядке?