很抱歉,标题太恐怖了……一口气解释我要问的内容并不容易。
我想在一个循环中运行两个相关的DML查询...如果其中一个查询失败/引发错误...我想回滚该事务,退出循环并在引发错误时终止整个proc (因此作业将检测到故障)。我认为我所拥有的是正确的...但是我有几个问题,因为我想更好地了解它的工作原理。我已经阅读了Microsoft文档...但是在某些方面仍不清楚。
我知道使用SET XACT_ABORT ON;
它将处理tran的回滚。这是否意味着我不需要检查IF (@@TRANCOUNT > 0)
块中的CATCH
?
另一个问题...我有TRY...CATCH
块的原因是由于WHILE
循环...我不确定失败的事务是否还会终止proc,所以我用THROW
强迫它吗?
这就是我所拥有的:(忽略它是一个无限循环的事实,我没有包括中断逻辑来使示例保持简单)
SET XACT_ABORT ON;
WHILE(1=1)
BEGIN
BEGIN TRY
BEGIN TRAN;
--DML Query 1
--DML Query 2
COMMIT TRAN;
END TRY
BEGIN CATCH
IF (@@TRANCOUNT > 0)
ROLLBACK TRAN;
THROW;
END CATCH
END
好的,我想自己弄清楚如何测试它,我很难弄清楚如何测试它,但是我想我现在已经掌握了。所以现在我很难发布问题:D
这是到目前为止我进行的测试...我将对其进行更改时对其进行更新。似乎IF (@@TRANCOUNT > 0)
块中的CATCH
并不是必需的,因为当我删除ROLLBACK
并在失败后检查事务时,没有开放的事务。但是,如果我将其留在...中,IF
语句将解析为true,并且仍然运行回滚而不会出错。
SET NOCOUNT ON;
IF OBJECT_ID('dbo.ChadTestTable1') IS NOT NULL DROP TABLE dbo.ChadTestTable1; --SELECT * FROM dbo.ChadTestTable1
CREATE TABLE dbo.ChadTestTable1 (TestField VARCHAR(10) NOT NULL)
IF OBJECT_ID('dbo.ChadTestTable2') IS NOT NULL DROP TABLE dbo.ChadTestTable2; --SELECT * FROM dbo.ChadTestTable2
CREATE TABLE dbo.ChadTestTable2 (TestField VARCHAR(10) NOT NULL)
INSERT INTO dbo.ChadTestTable1 (TestField) VALUES ('Test1')
INSERT INTO dbo.ChadTestTable2 (TestField) VALUES ('Test1')
SET XACT_ABORT ON;
WHILE(1=1)
BEGIN
BEGIN TRY
BEGIN TRAN;
RAISERROR('Update first table',0,1) WITH NOWAIT;
UPDATE dbo.ChadTestTable1 SET TestField = 'Test3'
RAISERROR('Update second table',0,1) WITH NOWAIT;
UPDATE dbo.ChadTestTable2 SET TestField = NULL
RAISERROR('Updates done',0,1) WITH NOWAIT;
COMMIT TRAN;
END TRY
BEGIN CATCH
--It appears this isn't necessary...but if it's here, it still resolves to true and runs?
IF (@@TRANCOUNT > 0)
BEGIN
RAISERROR('Rolling back transaction',0,1) WITH NOWAIT;
ROLLBACK TRAN;
END
RAISERROR('Throwing Error',0,1) WITH NOWAIT;
THROW;
END CATCH
RAISERROR('End of loop',0,1) WITH NOWAIT;
BREAK;
END
SELECT * FROM dbo.ChadTestTable1 ctt
SELECT * FROM dbo.ChadTestTable2 ctt
答案 0 :(得分:0)
所以我想出了自己的答案。我度过了一段相当艰难的时期,试图弄清楚如何自己进行测试,这就是为什么我提出了这个问题,但最终还是想出了办法。这就是我所发现的...您可能在Microsoft文档中可以找到90%的内容,但是我读到它后仍然感到困惑,所以我进行了蛮力测试。
这是我在阅读文档后发现的失踪之处:
XACT_ABORT ON
-它不仅回滚事务,而且还会引发终止错误... aka,如果它正在进行并且事务处于循环中,并且在tran中引发错误,它将回滚tran,中断循环,并且将结束proc,并且在运行之后将不执行任何操作。 proc /脚本到此结束。因此...我不需要TRY...CATCH
块来运行THROW
,并且我不需要回滚,因为它将自动完成。我很高兴发现这一点,因为这大大简化了我的代码。