Estou trabalhando no SQL Server 2008 R2.
Eu tenho um benefício de tabela que tem um gatilho AFTER INSERT, UPDATE chamado tiu_benefit .
Eu quero escrever uma instrução UPDATE para esta tabela atualizar 1 linha, mas não quero que seu gatilho seja acionado. Eu sei que posso desabilitar o gatilho antes de UPDATE e habilitar o gatilho após UPDATE :
DISABLE TRIGGER tiu_benefit ON benefit;
GO
UPDATE benefit SET editor = 'srh' where benefit_id = 9876
GO
ENABLE TRIGGER tiu_benefit ON benefit;
GO
Mas esse gatilho de desabilitação e habilitação afetará todos os usuários conectados no momento. Portanto, existe a possibilidade de outro usuário executar um UPDATE/INSERT enquanto o gatilho estiver desabilitado pelo meu script, o que não é bom. É por isso que eu só quero desabilitar e habilitar o gatilho para minha sessão atual. É possível? Se sim, por favor diga como.
Obrigado
Para resolver seu problema, temos que adotar uma abordagem programática para o problema. Existem duas rotas que você pode ir aqui. A razão para precisar dessas abordagens é porque você não pode desabilitar um gatilho para uma instrução específica, ele só pode ser desabilitado para a totalidade da tabela.
Opção 1: Context_Info()
Samuel Vanga em MS SQL Tips teve um ótimo exemplo:
Agora, quando Samuel não quer que o gatilho seja executado, eles usam isso:
Context_Info
usa as seguintes visualizações do sistema para obter informações sobre a sessão atual:sys.dm_exec_requests
sys.dm_exec_sessions
sys.sysprocesses
A ideologia aqui é que a string binária que você está definindo é exposta apenas à sessão atual, então quando o gatilho for executado durante sua sessão, ele verá o escopo e a configuração da variável da
Context_info
função e pulará para a parte de escape do gatilho em vez de.Opção 2: Tabela Temp.
Itzik Ben-Gan tem uma ótima solução em seu livro "Inside Microsoft SQL Server 2008 T-SQL Programming: T-SQL Programming" que também está em seu livro posterior T-SQL Querying . O principal problema com isso sobre a
context_info
função é a sobrecarga menor do TempDB.Para estragar a surpresa, mas não estragar o enredo dos livros (acho que vale a pena comprar e ler), você vai alterar seu gatilho.
Seu gatilho deve realizar uma verificação de uma tabela temporária. Se a tabela temporária existir, o gatilho deve saber encerrar e não executar as ações.
Na instrução de atualização que você deseja executar, crie primeiro a tabela temporária. Ele será visto na mesma transação que o gatilho e fará com que o gatilho ignore sua instrução.
Exemplo de gatilho:
Exemplo de instrução inicial quando você não deseja que o gatilho seja executado:
Colocando tudo para o seu exemplo:
Fiz alguns testes sobre isso e acho que você ficaria bem se executasse seu processo em uma única transação.
Nos meus testes, apenas destaquei e executei o
BEGIN TRANSACTION
e oDISABLE TRIGGER
primeiro. Em seguida, abri uma nova (segunda) janela de consulta e tentei executar várias instruções DML (SELECT
,INSERT
,UPDATE
DELETE
) na tabela base. Todas as tentativas de acessar a tabela base na segunda janela de consulta aguardaram os bloqueios mantidos pela janela com a transação explícita. Depois de confirmar (ou reverter) minha transação explícita, a segunda janela conseguiu acessar a tabela.Eu usaria um
CONTEXT_INFO
ou o mais recenteSESSION_CONTEXT
. Ambos são valores baseados em sessão.CONTEXT_INFO
é umVARBINARY(128)
valor único. Isso está disponível desde pelo menos o SQL Server 2000.CONTEXT_INFO
pode ser visualizado por qualquer pessoaVIEW SERVER STATE
, pois é um campo retornado pelosys.dm_exec_sessions
DMV. Já usei este e funciona muito bem.Definir via SET CONTEXT_INFO
Obter via CONTEXT_INFO() ou sys.dm_exec_sessions
Dependendo do tipo de valor que você está armazenando
CONTEXT_INFO
, há algumas nuances a serem observadas. Eu abordo isso no seguinte post do blog:Por que CONTEXT_INFO() não retorna o valor exato definido por SET CONTEXT_INFO?
Session_context é um par de
SQL_VARIANT
valores chave/valor. Isso foi introduzido no SQL Server 2016. A separação de valores para diferentes propósitos é bastante agradável. Session_context só pode ser visualizado pela sessão atual.Defina este valor via sp_set_session_context
Obtenha este valor via SESSION_CONTEXT
Uma coisa a considerar em relação à opção de tabela temporária local e até mesmo a opção de desabilitar / habilitar Trigger: ambas requerem alguma quantidade de atividade de bloqueio e tran log. Ambas as opções aumentam o potencial de contenção, mesmo que minimamente. As duas opções de "contexto" devem ser mais leves/somente memória.