AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 204339
Accepted
srh
srh
Asked: 2018-04-19 07:23:12 +0800 CST2018-04-19 07:23:12 +0800 CST 2018-04-19 07:23:12 +0800 CST

SQL Server: Como desabilitar o gatilho para uma atualização apenas para sua sessão atual?

  • 772

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

sql-server trigger
  • 3 3 respostas
  • 26603 Views

3 respostas

  • Voted
  1. Shaulinator
    2018-04-19T07:33:48+08:002018-04-19T07:33:48+08:00

    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:

    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
    

    Agora, quando Samuel não quer que o gatilho seja executado, eles usam isso:

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

    Context_Infousa 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_infofunçã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_infofunçã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:

    CREATE TRIGGER TRIGGERNAME ON TABLENAME for INSERT AS
    
    IF OBJECT_ID('tempdb..#FAKETEMPTABLE') IS NOT NULL RETURN;
    GO
    

    Exemplo de instrução inicial quando você não deseja que o gatilho seja executado:

    CREATE TABLE #FAKETEMPTABLE(col1 SMALLINT);
    

    Colocando tudo para o seu exemplo:

    ALTER TRIGGER tiu_benefit ON benefit FOR 
    ... 
    AS
    ...
    IF OBJECT_ID('tempdb..#FAKETEMPTABLE') IS NOT NULL RETURN;
    --... rest of code here
    GO
    
    CREATE TABLE #FAKETEMPTABLE(col1 SMALLINT);
    UPDATE benefit SET editor = 'srh' where benefit_id = 9876;
    GO
    
    • 21
  2. Best Answer
    Scott Hodgin - Retired
    2018-04-19T10:11:17+08:002018-04-19T10:11:17+08:00

    Fiz alguns testes sobre isso e acho que você ficaria bem se executasse seu processo em uma única transação.

    BEGIN TRANSACTION
    GO
    
    DISABLE TRIGGER tiu_benefit ON benefit;
    GO
    
    UPDATE benefit
    SET editor = 'srh'
    WHERE benefit_id = 9876
    GO
    
    ENABLE TRIGGER tiu_benefit ON benefit;
    GO
    
    --Decide to commit or rollback
    
    --commit
    --rollback 
    

    Nos meus testes, apenas destaquei e executei o BEGIN TRANSACTIONe o DISABLE TRIGGERprimeiro. 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.

    • 10
  3. Solomon Rutzky
    2018-04-19T11:55:46+08:002018-04-19T11:55:46+08:00

    Eu usaria um CONTEXT_INFOou o mais recente SESSION_CONTEXT. Ambos são valores baseados em sessão.

    • CONTEXT_INFOé um VARBINARY(128)valor único. Isso está disponível desde pelo menos o SQL Server 2000. CONTEXT_INFOpode ser visualizado por qualquer pessoa VIEW SERVER STATE, pois é um campo retornado pelo sys.dm_exec_sessionsDMV. 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_VARIANTvalores 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.

    • 3

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve