当前位置: 首页 > 知识库问答 >
问题:

尝试并捕获TSQL-捕获不捕获

宋健柏
2023-03-14

我有一个存储过程似乎没有正确记录错误。

代码有错误,但 catch 块似乎未生效。

try块相当长,但错误部分很简单,并且在最后出现,所以我已经对此进行了预测。

BEGIN TRY 
insert into tbl_X
select * from #temp_tbl_Y

RETURN 1
END TRY

BEGIN CATCH
    Insert Into ExtractsErrorLog
    SELECT 
    getdate() as ErrorDate 
    ,object_name(@@procid) as ProcedureName
    ,ERROR_NUMBER() as ErrorNumber
    ,ERROR_LINE() as ErrorLine
    ,ERROR_MESSAGE() as ErrorMessage
    ;
DECLARE @errormessage as varchar(max);
DECLARE @errorseverity as int;
DECLARE @errorstate as int;

set @errormessage = ERROR_MESSAGE();
set @errorseverity = ERROR_SEVERITY();
set @errorstate = ERROR_STATE();

 RAISERROR (@errormessage,
            @errorseverity,
            @errorstate
               );


END CATCH;

proc失败的错误是我们的老朋友“列名或提供的值的数量与表定义不匹配”。我已经修复了这个错误 - 这是一个愚蠢的懒惰错误 - 但我感到困惑为什么我的错误日志记录过程似乎没有工作 - 没有行入到我的 ExtractsErrorLog 表中。

共有3个答案

郑俊弼
2023-03-14

这是您的 RETURN:“无条件地从查询或过程中退出。RETURN 是即时和完整的,可以随时用于退出过程、批处理或语句块。

申屠秦斩
2023-03-14

我在日志记录的INSERT语句之前使用了THROW in CATCH块——得到了与您相同的问题。一旦我在日志插入语句后移动THROW,它就工作了。看起来THROW可能会终止会话。

您没有在代码示例中使用THROW,但认为这可能对其他人有所帮助。

苏磊
2023-03-14

泰美的尝试...“捕获”不会捕获该错误。此错误属于“编译/重新编译”类型的错误,这些错误不由 CATCH 块“在同一执行级别内”处理。

来自MSDN:

当下列类型的错误发生在与TRY…CATCH构造相同的执行级别时,CATCH块不处理这些错误:

>

  • 阻止批处理运行的编译错误(如语法错误)。

    在语句级重新编译期间发生的错误,例如由于延迟的名称解析而在编译后发生的对象名称解析错误

    您可以使用TRY…CATCH处理编译或语句级重新编译期间发生的错误,方法是在TRY块中的单独批处理中执行错误生成代码。例如,您可以通过将代码放入存储过程中或使用sp_executesql执行动态Transact-SQL语句来实现。这允许TRY…CATCH在比错误发生更高的执行级别捕获错误。例如,以下代码显示了生成对象名称解析错误的存储过程。包含TRY…CATCH构造的批处理在比存储过程更高的级别执行;并且捕获在较低级别发生的错误。

    我遇到了类似的问题,一个脚本在<code>TRY…CATCH<code>中创建了一个事务,如果事务失败,它将<code>回滚<code>该事务。事务中的一条语句抛出了相同的错误,并导致事务永远不会关闭,因为从未输入CATCH

    如 MSDN 文章中所述,一种替代方法是从 INSERT 语句创建一个存储过程,然后在 try/catch 中调用该过程。如果 sproc 错误,您将在尝试创建编译错误时捕获编译错误。如果表定义稍后更改为使 sproc 失效,则 TRY...捕获将为您捕获异常。

    如果希望它都在一个脚本中,可以将其设置为临时存储过程,但在创建存储过程时需要处理编译错误。这并不漂亮,但它会起作用:

    -- Creating error sproc to re-use code
    CREATE PROCEDURE #HandleError AS
        Insert Into ExtractsErrorLog
        SELECT  GETDATE() as ErrorDate 
                ,object_name(@@procid) as ProcedureName
                ,ERROR_NUMBER() as ErrorNumber
                ,ERROR_LINE() as ErrorLine
                ,ERROR_MESSAGE() as ErrorMessage;
    
        DECLARE @errormessage as varchar(max);
        DECLARE @errorseverity as int;
        DECLARE @errorstate as int;
    
        set @errormessage = ERROR_MESSAGE();
        set @errorseverity = ERROR_SEVERITY();
        set @errorstate = ERROR_STATE();
    
        RAISERROR ( @errormessage,
                    @errorseverity,
                    @errorstate);
    GO
    
    -- Create a stored procedure of our INSERT and catch any compilation errors
    CREATE PROCEDURE #TEST AS
        insert into tbl_X
        select * from #temp_tbl_Y
    GO
    IF (@@ERROR <> 0) BEGIN
        exec #HandleError
        -- If there was an error creating the sprocs, don't continue to the next batch
        RETURN
    END
    
    -- If compilation succeeded, then run the sproc
    BEGIN TRY 
        exec #TEST
        RETURN
    END TRY
    BEGIN CATCH
        exec #HandleError
    END CATCH;
    

  •  类似资料:
    • 问题内容: 我经常遇到如下情况: 仍然需要尝试-最终在内部捕获块。 克服此问题的最佳实践是什么? 问题答案: 写一个类,其中包含捕获和记录此类异常的方法,然后根据需要使用。 您最终会看到如下内容: 您的客户端代码将类似于: 更新: 自Java 7开始,各种JDBC接口都得到了扩展,而以上代码回答了原始问题,如果您直接针对JDBC API编写代码,则现在可以对其进行结构化:

    • 问题内容: 我只是在学习Java异常处理和Java。我制作了一个Swing GUI,用户将在两个字段中输入整数,然后单击带有算术函数的单选按钮,答案将出现在第三个文本字段中。我想包含一个try / catch块,以在用户将前两个字段之一留为空白或输入除整数以外的内容时捕获异常,以及如果用户尝试将其除以零则输入第二个catch。该窗体可以正常工作,但是不会捕获错误,只能返回堆栈跟踪并使程序崩溃。我感

    • 问题内容: 我有一个需要类似以下内容的场景 在我的尝试,我会,数据,将其与基于处理其他数据集。 在随后。有可能阻止吗?下面是伪代码: 问题答案: 无需创建表,您只需声明一个表变量(查询结束时该变量将自动消失)。

    • 我有一个返回< code>List的方法。现在我想知道如何正确放置< code>try/catch块。如果我将< code>return语句放在< code>try中,我会得到错误 并非所有代码路径都返回值 如果我放置在之后(就像我目前所做的那样),即使在之后,它也会返回。那么最好的方法应该是什么? 方法如下:

    • 我已经写了一个节点。使用express框架的jsapi。我正在使用wait和async。我在try-catch块中捕获异步函数。但是,在catch(err)方法中,不会返回err。 在上面的例子中,我故意调用一个不存在的函数,这样它就会抛出一个错误。 我得到的答复如下。它正在命中catch块,但没有将错误添加到数据对象中。 但是,如果我将下面的行移出try catch块。控制台将抛出以下错误。 所

    • 前几天,我在我们的一个项目中看到一些代码,它们使用try-catch并重新抛出捕获的异常,如下所示: 除了catch块中的异常之外,没有做任何其他操作,所以我甚至不确定它为什么会被抛出。我看不出再次抛出同一个异常并对该异常不做任何处理有什么好处。 如果重新抛出catch块中捕获的异常,C#如何处理?它是否陷入了无限抛接球循环?还是说它最终会放弃试一试?