Подтвердить что ты не робот

Есть ли способ отключить запуск SQL Server только для определенной области выполнения?

В SQL Server 2005 есть ли способ, чтобы триггер обнаружил, какой объект отвечает за запуск триггера? Я хотел бы использовать это, чтобы отключить триггер для одной хранимой программы.

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

DISABLE TRIGGER { [ schema_name . ] trigger_name [ ,...n ] | ALL } ON { object_name | DATABASE | ALL SERVER } [ ; ]

ENABLE TRIGGER { [ schema_name . ] trigger_name [ ,...n ] | ALL } ON { object_name | DATABASE | ALL SERVER } [ ; ]

Если возможно, я хотел бы избежать техники наличия поля "NoTrigger" в моей таблице и выполнения NoTrigger = null, потому что я хотел бы держать таблицу как можно меньшей.

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

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

От: http://searchsqlserver.techtarget.com/tip/1,289483,sid87_gci1170220,00.html#trigger

4b9b3361

Ответ 1

Я недавно увидел эту статью, недавно выделенную в выпуске бюллетеня SQL Server Central, и, как представляется, он предлагает способ, который может оказаться полезным с помощью Context_Info в соединении:

http://www.mssqltips.com/tip.asp?tip=1591


РЕДАКТИРОВАТЬ Terrapin:

Вышеупомянутая ссылка включает следующий код:

USE AdventureWorks;  
GO  
-- creating the table in AdventureWorks database  
IF OBJECT_ID('dbo.Table1') IS NOT NULL  
DROP TABLE dbo.Table1  
GO  
CREATE TABLE dbo.Table1(ID INT)  
GO   
-- Creating a trigger  
CREATE TRIGGER TR_Test ON dbo.Table1 FOR INSERT,UPDATE,DELETE  
AS  
DECLARE @Cinfo VARBINARY(128)  
SELECT @Cinfo = Context_Info()  
IF @Cinfo = 0x55555  
RETURN  
PRINT 'Trigger Executed'  
-- Actual code goes here  
-- For simplicity, I did not include any code  
GO  

Если вы хотите предотвратить запуск триггера, вы можете сделать следующее:

SET Context_Info 0x55555 
INSERT dbo.Table1 VALUES(100)

Ответ 2

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

Я предлагаю запретить разрешения на обновление таблиц, если ничего не работает.

Это также решает проблему дублирования кода. Дублирование кода в SP обновления и в триггере является нарушением хороших принципов разработки программного обеспечения и будет проблемой обслуживания.

Ответ 4

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

Ответ 5

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

IF OBJECT_ID('dbo.TriggerTest') IS NOT NULL
 DROP PROCEDURE dbo.TriggerTest
GO

CREATE PROCEDURE [dbo].[TriggerTest]
AS
BEGIN TRANSACTION trnInsertTable1s
;
DISABLE TRIGGER trg_tblTable1_IU ON tblTable1
;
BEGIN -- Procedure Code
    PRINT '@@trancount'
    PRINT @@TRANCOUNT
    -- Do Stuff

END -- Procedure Code
;
ENABLE TRIGGER trg_tblTable1_IU ON tblTable1

IF @@ERROR <> 0 ROLLBACK TRANSACTION
ELSE COMMIT TRANSACTION

Ответ 6

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

Почему вы хотите отключить триггер? Что оно делает? Почему это вызвало проблему? Как правило, плохая идея отключить тигр с точки зрения целостности данных.

Ответ 7

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

Ответ 8

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

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

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

Ответ 9

Я согласен с некоторыми другими ответами. Не выключайте триггер.

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

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

Ответ 10

Я только столкнулся с той же проблемой и придумал следующее решение, которое работает для меня.

  • Создайте постоянную таблицу БД, содержащую одну запись для каждого триггера, который вы хотите отключить (например, refTriggerManager); каждая строка содержит имя триггера (например, strTriggerName = 'myTrigger') и флаг бита (например, blnDisabled, по умолчанию 0).

  • В начале тела триггера просмотрите strTriggerName = 'myTrigger' в refTriggerManager. Если blnDisabled = 1, вернитесь без выполнения остальной части кода запуска, а затем продолжите выполнение кода запуска.

  • В сохраненной процедуре, в которой вы хотите отключить триггер, выполните следующие действия:


НАЧАТЬ ПЕРЕДАЧУ

UPDATE refTriggerManager SET blnDisabled = 1 WHERE strTriggerName = 'myTrigger'

/* ОБНОВЛЯЙТЕ таблицу, которой принадлежит "myTrigger" , но которую вы хотите отключить. Поскольку refTriggerManager.blnDisabled = 1, "myTrigger" возвращается без выполнения его кода. */

UPDATE refTriggerManager SET blnDisabled = 0 WHERE triggerName = 'myTrigger'

/* Дополнительный финальный код UPDATE, запускающий триггер. Поскольку refTriggerManager.blnDisabled = 0, "myTrigger" выполняется полностью. */

COMMIT TRANSACTION


Все это происходит внутри транзакции, поэтому она изолирована от внешнего мира и не влияет на другие UPDATE в целевой таблице.

Кто-нибудь видит какие-либо проблемы с этим подходом?

Билл

Ответ 11

вы можете использовать функцию Exec 'для включения и запуска триггеров из хранимой процедуры. Пример: EXEC ('ENABLE TRIGGER dbo.TriggerName on dbo.TriggeredTable')