zoukankan      html  css  js  c++  java
  • SQL Server Try Catch 异常捕捉

    SQL Server Try Catch 异常捕捉

    背景

    今天遇到一个关于try catch 使用比较有意思的问题。如下一段代码:

    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

    第一次执行时,无法正常捕捉到错误,并执行catch的代码,返回错误信息
    这里写图片描述
    第二次执行,就能正常捕捉。且后续再执行就都正常了。
    这里写图片描述
    同样的代码,执行2次出现完全不同的结果。这是很让人费解的。

    分析

    首先 看第一次执行报错,看这个错误的级别编号是16。
    try catch 不能捕捉什么样的错误

    严重级别为 10 或更低的错误,属于警告或信息性消息。
    严重级别为 20 或更高且终止会话的 SQL Server 数据库引擎任务处理的错误。此类问题过于严重数据库引擎会直接终止会话。所以无法往后继续执行。

    总之,就是能捕捉严重级别大于10,且不会严重到之前终止会话的错误

    关于严重级别 和 描述:
    https://docs.microsoft.com/zh-cn/sql/relational-databases/errors-events/database-engine-error-severities?view=sql-server-2017 “数据库引擎错误严重性”

    那我们前面的例子错误级别16,的确是属于可以捕捉的情况。那为什么会有这个问题。跟执行计划的产生有关系。因为你第一次执行的时候,SQL server 在需要编译SQL 语句,产生执行计划。就是这个时候执行计划还没有。所以他无法往下面继续执行。就无法CATCH到。第二次,以及后面几次再执行,因为已经缓存了执行计划。所以可以catch到。

    我们执行完第一次之后可以查看对应的执行计划
    这里写图片描述
    然后再执行,就可以成功捕捉了。如果我们把执行计划清除掉
    DBCC FREEPROCCACHE 或者使用option(recomplile)进行重编译。那么结果就会是一直无法捕捉。
    这里写图片描述

  • 相关阅读:
    POJ 1659 Frogs' Neighborhood
    zoj 2913 Bus Pass(BFS)
    ZOJ 1008 Gnome Tetravex(DFS)
    POJ 1562 Oil Deposits (DFS)
    zoj 2165 Red and Black (DFs)poj 1979
    hdu 3954 Level up
    sgu 249 Matrix
    hdu 4417 Super Mario
    SPOJ (BNUOJ) LCM Sum
    hdu 2665 Kth number 划分树
  • 原文地址:https://www.cnblogs.com/Siny0/p/11190034.html
Copyright © 2011-2022 走看看