我有一个更大的存储过程,它利用多个 TRY/CATCH 块来捕获并记录各个错误。我还在过程的整个内容周围封装了一个事务,以便能够在沿途某个地方发生错误时回滚整个过程(以防止大量混乱的清理); XACT_ABORT 已启用,否则它不会回滚整个事务。
关键部件:
我的数据库中有一个表,每次运行此过程时都会插入一条记录,其中包含操作结果和出错的详细信息。
有趣的事情正在发生 - 实际上,当我最终弄清楚出了什么问题时,很明显......日志表中的插入语句也被回滚,因此,如果我没有从 SSMS 中运行它,我将无法看到它是否已运行,因为回滚会删除所有活动痕迹。
问题:
除了这个单个插入语句之外,是否可以回滚整个事务?我仍然想保留在存储过程运行期间编译的错误消息。
非常感谢!
~Eli
更新6/28
这是我正在查看的代码示例。此示例与 @Alex 和 @gameiswar 提供的示例之间的主要区别在于,在我的情况下,try/catch 块全部嵌套在单个事务内。这样做的目的是有多个捕获(对于多个表),尽管即使最后一次更新失败,我们也会回滚整个混乱。
SET XACT_ABORT ON;
BEGIN TRANSACTION
DECLARE @message AS VARCHAR(MAX) = '';
-- TABLE 1
BEGIN TRY
UPDATE TABLE xx
SET yy = zz
END TRY
BEGIN CATCH
SET @message = 'TABLE 1 '+ ERROR_MESSAGE();
INSERT INTO LOGTABLE
SELECT
GETDATE(),
@message
RETURN;
END CATCH
-- TABLE 2
BEGIN TRY
UPDATE TABLE sss
SET tt = xyz
END TRY
BEGIN CATCH
SET @message = 'TABLE 2 '+ ERROR_MESSAGE();
INSERT INTO LOGTABLE
SELECT
GETDATE(),
@message
RETURN;
END CATCH
COMMIT TRANSACTION
您可以尝试如下所示的操作,这可确保您记录操作。这利用了表变量不会回滚的事实。
伪代码仅供参考:
create table test1
(
id int primary key
)
create table logg
(
errmsg varchar(max)
)
declare @errmsg varchar(max)
set xact_abort on
begin try
begin tran
insert into test1
select 1
insert into test1
select 1
commit
end try
begin catch
set @errmsg=ERROR_MESSAGE()
select @errmsg as "in block"
if @@trancount>0
rollback tran
end catch
set xact_abort off
select @errmsg as "after block";
insert into logg
select @errmsg
select * from logg
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)