关于SQL中的Try Catch

百里依玉 2018-05-28 01:51:14
SELECT  @@TRANCOUNT AS A
SET XACT_ABORT ON ;
BEGIN TRY
BEGIN TRAN
SELECT @@TRANCOUNT AS A1

INSERT INTO A2A ( ID1 )
VALUES ( 'A' )

COMMIT TRAN;
END TRY
BEGIN CATCH
SELECT @@TRANCOUNT AS A2

ROLLBACK TRAN;

SELECT ERROR_MESSAGE() AS ErrorMessage ,
ERROR_SEVERITY() AS ErrorSeverity ,
ERROR_STATE() AS ErrorState
END CATCH

SELECT @@TRANCOUNT AS B


各位大神,如上语句,A2A 表是不存在的,现在想用Catch获取到异常!
现在遇到的问题是有时候能取到异常,有时候直接报错,如下图
正常catch到异常的:

直接终止并报错的
...全文
792 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiaoxiangqing 2018-05-29
  • 打赏
  • 举报
回复
有些错误用catch是不行的
百里依玉 2018-05-29
  • 打赏
  • 举报
回复
好的,谢谢各位了!
OwenZeng_DBA 2018-05-29
  • 打赏
  • 举报
回复
这是一个比较有意思的问题。这是因为你第一次执行的时候,SQL server 在需要编译SQL 语句,产生执行计划。就是这个时候执行计划还没有。所以他无法往下面继续执行。就无法CATCH到。第二次,以及后面几次再执行,因为已经缓存了执行计划。所以可以catch到。 这种情况,其实最好是自己在代码做好判断,这个表是不是存在。
zjcxc 2018-05-29
  • 打赏
  • 举报
回复
TRY CTCH 捕获的是执行时的错误 如果你的表不存在,那么第一次执行的时候会生成执行计划,这个时候会直接出错,因为生成执行计划还没有到执行这块,所以 TRY CATCH 无法捕获错误 你可以使用 OPTION(RECOMPILE) 指示每次都要编译,就会发现无论如何 你都不会捕获到错误了
SET XACT_ABORT OFF
SELECT  @@TRANCOUNT AS A
BEGIN TRY  
            BEGIN TRAN
            SELECT  @@TRANCOUNT AS A1
 
            INSERT  INTO A2A ( ID1 )
            VALUES  ( 'A' )
 OPTION(RECOMPILE)
            COMMIT TRAN;  
END TRY  
BEGIN CATCH  
            SELECT  @@TRANCOUNT AS A2
 
            ROLLBACK TRAN; 
 
            SELECT  ERROR_MESSAGE() AS ErrorMessage ,
                    ERROR_SEVERITY() AS ErrorSeverity ,
                    ERROR_STATE() AS ErrorState  
END CATCH  
 
SELECT  @@TRANCOUNT AS B
百里依玉 2018-05-28
  • 打赏
  • 举报
回复
引用 5 楼 z10843087 的回复:
你如果不加SET XACT_ABORT =ON ,第一次失败,第二次捕获成功的语句发来看看
SELECT  @@TRANCOUNT AS A
BEGIN TRY  
			BEGIN TRAN
            SELECT  @@TRANCOUNT AS A1

            INSERT  INTO A2A ( ID1 )
            VALUES  ( 'A' )

            COMMIT TRAN;  
END TRY  
BEGIN CATCH  
            SELECT  @@TRANCOUNT AS A2

            ROLLBACK TRAN; 

            SELECT  ERROR_MESSAGE() AS ErrorMessage ,
                    ERROR_SEVERITY() AS ErrorSeverity ,
                    ERROR_STATE() AS ErrorState  
END CATCH  

SELECT  @@TRANCOUNT AS B
OwenZeng_DBA 2018-05-28
  • 打赏
  • 举报
回复
你如果不加SET XACT_ABORT =ON ,第一次失败,第二次捕获成功的语句发来看看
百里依玉 2018-05-28
  • 打赏
  • 举报
回复
引用 3 楼 z10843087 的回复:
[quote=引用 2 楼 hero1044617901 的回复:] [quote=引用 1 楼 z10843087 的回复:] 这就是SET XACT_ABORT 的工作机制。 当 SET XACT_ABORT 为 ON 时,如果执行 Transact-SQL 语句产生运行时错误,则整个事务将终止并回滚。 当 SET XACT_ABORT 为 OFF 时,有时只回滚产生错误的 Transact-SQL 语句,而事务将继续进行处理。如果错误很严重,那么即使 SET XACT_ABORT 为 OFF,也可能回滚整个事务。OFF 是默认设置。
您是说同样的执行可能出现不同的结果?那如果我字段或表发生了变化,我想获取这个异常并回滚应该怎么做呢?[/quote] 你现在2个执行的不一样啊,一个有 SET XACT_ABORT =ON ,一个没有,如果想要捕捉就不用用 SET XACT_ABORT =ON[/quote] 默认不写SET XACT_ABORT =ON 第一次执行失败,第二次就能捕获异常是什么原因呢
OwenZeng_DBA 2018-05-28
  • 打赏
  • 举报
回复
引用 2 楼 hero1044617901 的回复:
[quote=引用 1 楼 z10843087 的回复:] 这就是SET XACT_ABORT 的工作机制。 当 SET XACT_ABORT 为 ON 时,如果执行 Transact-SQL 语句产生运行时错误,则整个事务将终止并回滚。 当 SET XACT_ABORT 为 OFF 时,有时只回滚产生错误的 Transact-SQL 语句,而事务将继续进行处理。如果错误很严重,那么即使 SET XACT_ABORT 为 OFF,也可能回滚整个事务。OFF 是默认设置。
您是说同样的执行可能出现不同的结果?那如果我字段或表发生了变化,我想获取这个异常并回滚应该怎么做呢?[/quote] 你现在2个执行的不一样啊,一个有 SET XACT_ABORT =ON ,一个没有,如果想要捕捉就不用用 SET XACT_ABORT =ON
百里依玉 2018-05-28
  • 打赏
  • 举报
回复
引用 1 楼 z10843087 的回复:
这就是SET XACT_ABORT 的工作机制。 当 SET XACT_ABORT 为 ON 时,如果执行 Transact-SQL 语句产生运行时错误,则整个事务将终止并回滚。 当 SET XACT_ABORT 为 OFF 时,有时只回滚产生错误的 Transact-SQL 语句,而事务将继续进行处理。如果错误很严重,那么即使 SET XACT_ABORT 为 OFF,也可能回滚整个事务。OFF 是默认设置。
您是说同样的执行可能出现不同的结果?那如果我字段或表发生了变化,我想获取这个异常并回滚应该怎么做呢?
OwenZeng_DBA 2018-05-28
  • 打赏
  • 举报
回复
这就是SET XACT_ABORT 的工作机制。 当 SET XACT_ABORT 为 ON 时,如果执行 Transact-SQL 语句产生运行时错误,则整个事务将终止并回滚。 当 SET XACT_ABORT 为 OFF 时,有时只回滚产生错误的 Transact-SQL 语句,而事务将继续进行处理。如果错误很严重,那么即使 SET XACT_ABORT 为 OFF,也可能回滚整个事务。OFF 是默认设置。

22,209

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧