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 / 8693
Accepted
garik
garik
Asked: 2011-12-03 07:30:57 +0800 CST2011-12-03 07:30:57 +0800 CST 2011-12-03 07:30:57 +0800 CST

Por que TRY CATCH não suprime a exceção no gatilho

  • 772

Tenho uma trigger em uma tabela ( source ) que os dados devem ser copiados para a outra ( target ) em outro banco de dados. Estou tentando implementar o processo de sincronização personalizado para dados: quero que o banco de dados de destino (tabela) esteja atualizado para o banco de dados de origem (tabela). Tenho 3 centenas de tabelas para sincronizar. Alguns deles têm estrutura de dados física diferente. Não posso usar abordagens padrão do Sql Server (replicação, DTS...) devido a diferentes esquemas de dados e outras restrições (tempo de implementação, problemas de ambiente...). Meu objetivo é: esse gatilho NÃO deve impactar em INSERT, DELETE, UPDATE de registros em uma tabela de origem. Eu tentei assim solução:

CREATE TRIGGER dbo.MyTrigger
...
   AFTER INSERT
....
BEGIN TRY
     --RAISERROR('Test error', 16, 2)
END TRY
BEGIN CATCH
  -- nothing
END CATCH

Eu inseri RAISEERRORpara simular erro. Eu esperava, try/catchsuprimido que o erro e o registro foram inseridos (excluídos ou atualizados) com sucesso. Não. Não funciona. Eu tenho erro:

Foi gerado um erro durante a execução do gatilho. O lote foi abortado e a transação do usuário, se houver, foi revertida.

É possível realizar minha solução dessa maneira. Como posso capturar e segurar (suprimir) qualquer erro no meu gatilho?

Que sentido usar try/catchno trigger se não funcionar?

sql-server-2008 trigger
  • 2 2 respostas
  • 26155 Views

2 respostas

  • Voted
  1. Best Answer
    gbn
    2011-12-03T08:06:57+08:002011-12-03T08:06:57+08:00

    A transação está condenada a praticamente qualquer exceção e deve ser revertida.

    De "Usando TRY...CATCH no Transact-SQL" no MSDN

    Dentro de uma construção TRY…CATCH, as transações podem entrar em um estado no qual a transação permanece aberta, mas não pode ser confirmada. A transação não pode executar nenhuma ação que gere uma gravação no log de transações, como modificar dados ou tentar reverter para um ponto de salvamento. No entanto, neste estado, os bloqueios adquiridos pela transação são mantidos, e a conexão também é mantida aberta. Os efeitos da transação não são revertidos até que uma instrução ROLLBACK seja emitida ou até que o lote termine e a transação seja revertida automaticamente pelo Mecanismo de Banco de Dados. Se nenhuma mensagem de erro foi enviada quando a transação entrou em um estado não confirmável, quando o lote terminar, uma mensagem de erro será enviada ao aplicativo cliente indicando que uma transação não confirmável foi detectada e revertida.

    Uma transação entra em um estado não confirmável dentro de um bloco TRY quando ocorre um erro que, de outra forma, teria encerrado a transação. Por exemplo, a maioria dos erros de uma instrução DDL (linguagem de definição de dados) (como CREATE TABLE), ou a maioria dos erros que ocorrem quando SET XACT_ABORT é definido como ON, encerra a transação fora de um bloco TRY, mas torna uma transação não confirmável dentro de um bloco TRY .

    Este exemplo mostra o porquê. XACT_STATE() não registra uma transação implícita (por exemplo, nenhum BEGIN TRAN explícito)

    CREATE TABLE TrgTest (gbn int NOT NULL);
    GO
    CREATE TRIGGER TRG_TrgTEst_I ON TrgTest AFTER INSERT
    AS
    BEGIN TRY
         SELECT '1', @@TRANCOUNT, XACT_STATE();
         RAISERROR('Test error', 16, 2);
    END TRY
    BEGIN CATCH
         SELECT '2', @@TRANCOUNT, XACT_STATE();
    END CATCH
    GO
    
    BEGIN TRANSACTION
    INSERT TrgTest VALUES (1)
    SELECT 'will not run'
    GO
    SELECT 'next batch'
    GO
    
    
    BEGIN TRY
        BEGIN TRANSACTION
        SELECT 'a', @@TRANCOUNT, XACT_STATE();
        INSERT TrgTest VALUES (1)
        SELECT 'b', @@TRANCOUNT, XACT_STATE();
    END TRY
    BEGIN CATCH
        SELECT ERROR_MESSAGE()
        SELECT 'c', @@TRANCOUNT, XACT_STATE();
    END CATCH
    GO
    
    DROP TABLE TrgTest;
    
    • 7
  2. Beekir
    2018-04-10T12:41:27+08:002018-04-10T12:41:27+08:00

    Encontrei uma solução um pouco arriscada* que suprime "transações não confirmáveis" que ocorrem em um gatilho DML.

    Cuidado: geralmente não é seguro suprimir erros de transação em um gatilho, então pense muito antes de tentar fazer isso. Esse método é extremamente inseguro se houver outros gatilhos DML na mesma tabela, porque você pode estar confirmando dados inválidos que outro gatilho pretende reverter.

    Para suprimir erros graves que ocorrem em seu gatilho DML:

    1. Confirme a transação pré-existente implícita que representa o comando INSERT/UPDATE/DELETE inicial
    2. Dentro de um bloco TRY, use sp_executesql para tentar seu negócio arriscado.
    3. No final do seu gatilho, inicie uma nova transação. Isso evitará o erro 3609: a transação terminou no gatilho.
    • 0

relate perguntas

  • Melhores práticas para conectar bancos de dados que estão em diferentes regiões geográficas

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

  • Quanto "Padding" coloco em meus índices?

  • Existe um processo do tipo "práticas recomendadas" para os desenvolvedores seguirem para alterações no banco de dados?

  • Downgrade do SQL Server 2008 para 2005

Sidebar

Stats

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

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

    • 4 respostas
  • Marko Smith

    Como você mostra o SQL em execução em um banco de dados Oracle?

    • 2 respostas
  • Marko Smith

    Como selecionar a primeira linha de cada grupo?

    • 6 respostas
  • Marko Smith

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

    • 10 respostas
  • Marko Smith

    Posso ver Consultas Históricas executadas em um banco de dados SQL Server?

    • 6 respostas
  • Marko Smith

    Como uso currval() no PostgreSQL para obter o último id inserido?

    • 10 respostas
  • Marko Smith

    Como executar o psql no Mac OS X?

    • 11 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
  • Marko Smith

    Passando parâmetros de array para um procedimento armazenado

    • 12 respostas
  • Martin Hope
    Manuel Leduc Restrição exclusiva de várias colunas do PostgreSQL e valores NULL 2011-12-28 01:10:21 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Stuart Blackler Quando uma chave primária deve ser declarada sem cluster? 2011-11-11 13:31:59 +0800 CST
  • Martin Hope
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +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
  • Martin Hope
    BrunoLM Guid vs INT - Qual é melhor como chave primária? 2011-01-05 23:46:34 +0800 CST
  • Martin Hope
    bernd_k Quando devo usar uma restrição exclusiva em vez de um índice exclusivo? 2011-01-05 02:32:27 +0800 CST
  • Martin Hope
    Patrick Como posso otimizar um mysqldump de um banco de dados grande? 2011-01-04 13:13:48 +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