Вопрос

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

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

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

Это было полезно?

Решение

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

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

Можно ли правильно использовать триггеры?Абсолютно.

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

Другие советы

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

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

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

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

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

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

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

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

enter image description here

Я работаю с веб-приложениями и winforms на c #, и я НЕНАВИСТЬ срабатывает со страстью.Я никогда не сталкивался с ситуацией, когда я мог бы оправдать использование триггера перемещением этой логики на бизнес-уровень приложения и репликацией логики триггера там.

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

Некоторые причины, по которым мне не нравятся триггеры:

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

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

"Никогда не создавайте триггер для проверки ограничений целостности, который пересекает строки в таблице" - я не могу согласиться.Вопрос помечен как "SQL Server", и предложения CHECK constraints в SQL Server не могут содержать подзапрос;хуже того, реализация, похоже, имеет "жестко закодированное" предположение, что ПРОВЕРКА будет включать только одну строку, поэтому использование функции ненадежно.Итак, если мне нужно ограничение, которое на законных основаниях включает более одной строки - и хорошим примером здесь является упорядоченный первичный ключ в классической временной таблице "действительного времени", где мне нужно предотвратить перекрывающиеся периоды для одного и того же объекта - как я могу это сделать без триггера?Помните, что это первичный ключ, который обеспечивает целостность моих данных, поэтому о его применении где бы то ни было, кроме СУБД, не может быть и речи.Пока контрольные ограничения не получат подзапросы, я не вижу альтернативы использованию триггеров для определенных видов ограничений целостности.

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

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

  • это дополнительный уровень кода для исследования
  • иногда, как выяснил OP, когда вам нужно выполнить исправление данных, триггер может выполнять действия, исходя из предположения, что изменение данных всегда происходит с помощью директивы приложения, а не от разработчика или администратора базы данных, устраняющего проблему, или даже из другого приложения

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

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

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

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

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

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

Впервые я использовал триггеры пару недель назад.Мы переключились на рабочем сервере с SQL 2000 на SQL 2005 и обнаружили, что драйверы ведут себя по-разному с полями NText (хранящими большой XML-документ), удаляя последний байт.Я использовал триггер в качестве временного исправления, чтобы добавить дополнительный фиктивный байт (пробел) в конец данных, решая нашу проблему до тех пор, пока не будет найдено подходящее решение.

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

Честно говоря, это единственный раз, когда я использую триггеры для имитации уникального индекса, которому разрешено иметь значение NULL, которое не учитывается для уникальности.

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

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

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

Общий вентилятор,

но на самом деле использовать его нужно экономно, когда,

  • Необходимо поддерживать согласованность (особенно когда таблицы измерений используются на складе, и нам нужно связать данные в таблице фактов с их правильным измерением .Иногда вычисление правильной строки в таблице измерений может быть очень дорогостоящим, поэтому вы хотите, чтобы ключ был записан прямо в таблицу фактов, и один из хороших способов сохранить это "отношение" - использовать trigger .

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

Некоторые СУБД, такие как sql server 2005, также предоставляют вам триггеры для операторов CREATE / ALTER / DROP (чтобы вы могли знать, кто какую таблицу создал, когда, какой столбец удалил, когда и т.д.)

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

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

Кроме того, в MS SQL Server триггеры запускаются один раз для каждой команды sql, а не для каждой строки.Например, следующий оператор sql выполнит триггер только один раз.

UPDATE tblUsers
SET Age = 11
WHERE State = 'NY'

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top