AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 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

为什么 TRY CATCH 不会抑制触发器中的异常

  • 772

我在一个表(源)上有一个触发器,数据应该被复制到另一个数据库中的另一个(目标)。我正在尝试为数据实现自定义同步过程:我希望目标数据库(表)将是最新的源数据库(表)。我有 300 张表要同步。其中一些具有不同的物理数据结构。由于不同的数据架构和其他限制(实施时间、环境问题...),我无法使用 Sql Server 的标准方法(复制、DTS ...)。我的目标是:此触发器不应影响源表中记录的 INSERT、DELETE、UPDATE。我试过这样的解决方案:

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

我已插入RAISEERROR以模拟错误。我希望try/catch抑制该错误并成功插入(删除或更新)记录。不。这没用。我收到错误:

触发器执行期间引发错误。批处理已中止,并且用户事务(如果有)已回滚。

是否有可能以这种方式实现我的解决方案。如何捕获并保持(抑制)触发器中的任何错误?

try/catch如果它不起作用,在触发器中使用什么意义?

sql-server-2008 trigger
  • 2 2 个回答
  • 26155 Views

2 个回答

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

    几乎所有异常都注定了该事务,必须回滚。

    来自MSDN 上的“在 Transact-SQL 中使用 TRY...CATCH”

    在 TRY…CATCH 构造中,事务可以进入事务保持打开但不能提交的状态。事务不能执行任何会生成事务日志写入的操作,例如修改数据或尝试回滚到保存点。但是,在这种状态下,事务获取的锁保持不变,连接也保持打开状态。在发出 ROLLBACK 语句或批处理结束并且数据库引擎自动回滚事务之前,事务的效果不会逆转。如果在事务进入不可提交状态时没有发送错误消息,则当批处理完成时,将向客户端应用程序发送一条错误消息,指示检测到不可提交事务并回滚。

    当发生错误时,交易进入 TRY 块内的不可提交状态,否则该错误将结束交易。例如,来自数据定义语言 (DDL) 语句(例如 CREATE TABLE)的大多数错误,或者当 SET XACT_ABORT 设置为 ON 时发生的大多数错误,会在 TRY 块外终止事务,但在 TRY 块内使事务不可提交.

    这个例子说明了原因。XACT_STATE() 不注册隐含事务(例如,没有显式 BEGIN TRAN)

    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

    我发现了一个有点冒险的*解决方法,它可以抑制在 DML 触发器中发生的“不可提交的事务”。

    警告:在触发器中抑制事务错误通常是不安全的,因此在尝试执行此操作之前要仔细考虑。如果同一个表上还有其他 DML 触发器,则此方法非常不安全,因为您可能正在提交另一个触发器打算回滚的无效数据。

    要抑制 DML 触发器中发生的严重错误:

    1. 提交表示初始 INSERT/UPDATE/DELETE 命令的隐式预先存在的事务
    2. 在 TRY 块内,使用 sp_executesql 来尝试有风险的业务。
    3. 在触发器的最后,开始一个新的事务。这将防止错误 3609:事务在触发器中结束。
    • 0

相关问题

  • 连接不同地理区域的数据库的最佳实践

  • 死锁的主要原因是什么,可以预防吗?

  • 我在索引上放了多少“填充”?

  • 是否有开发人员遵循数据库更改的“最佳实践”类型流程?

  • 从 SQL Server 2008 降级到 2005

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    您如何显示在 Oracle 数据库上执行的 SQL?

    • 2 个回答
  • Marko Smith

    如何选择每组的第一行?

    • 6 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    我可以查看在 SQL Server 数据库上运行的历史查询吗?

    • 6 个回答
  • Marko Smith

    如何在 PostgreSQL 中使用 currval() 来获取最后插入的 id?

    • 10 个回答
  • Marko Smith

    如何在 Mac OS X 上运行 psql?

    • 11 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Marko Smith

    将数组参数传递给存储过程

    • 12 个回答
  • Martin Hope
    Manuel Leduc PostgreSQL 多列唯一约束和 NULL 值 2011-12-28 01:10:21 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Stuart Blackler 什么时候应该将主键声明为非聚集的? 2011-11-11 13:31:59 +0800 CST
  • Martin Hope
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    BrunoLM Guid vs INT - 哪个更好作为主键? 2011-01-05 23:46:34 +0800 CST
  • Martin Hope
    bernd_k 什么时候应该使用唯一约束而不是唯一索引? 2011-01-05 02:32:27 +0800 CST
  • Martin Hope
    Patrick 如何优化大型数据库的 mysqldump? 2011-01-04 13:13:48 +0800 CST

热门标签

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

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve