【发布时间】:2019-06-18 17:01:41
【问题描述】:
对不起这个可怕的标题......我在一行中要解释什么并不容易。
我想在一个循环中运行两个依赖的 DML 查询...如果其中一个查询失败/抛出错误...我想回滚事务,退出循环,并在抛出错误时终止整个过程(因此作业将检测到故障)。我认为我所拥有的是正确的......但我有几个问题,因为我想更好地了解它是如何工作的。我已经阅读了 Microsoft 文档...但我仍然不清楚某些事情。
我知道通过使用SET XACT_ABORT ON; 它将处理 tran 的回滚。这是否意味着我不需要在CATCH 块中检查IF (@@TRANCOUNT > 0)?
另一个问题...我有 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
这是我到目前为止所做的测试...我会在对其进行更改时对其进行更新。看来CATCH 块中的IF (@@TRANCOUNT > 0) 不是必需的,因为当我删除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
【问题讨论】:
标签: sql-server tsql transactions try-catch