SQL Server最终尝试捕获

时间:2014-09-11 14:17:47

标签: sql sql-server tsql

我有一个场景需要类似.NET's try-catch-finally block.

的内容

在我尝试的时候,我会CREATE a #temp tableINSERT数据给它&根据{{​​1}}处理其他数据集。

#temp然后CATCH。 是否可以RAISERROR阻止FINALLY? 以下是伪代码:

DROP #temp

7 个答案:

答案 0 :(得分:23)

虽然与FINALLY不完全相同,但Try-Catch的T-SQL版本确实允许在END CATCH语句结束后可以发生Try和Catch块之后需要执行的代码。 使用问题代码作为示例:

    BEGIN TRY
      CREATE TABLE #temp
       (
         --columns
       )
      --Process data with other data sets
    END TRY
    BEGIN CATCH
    EXECUTE usp_getErrorMessage
    END CATCH;

IF OBJECT_ID('tempdb..#temp') IS NOT NULL -- Check for table existence
    DROP TABLE #temp;

无论Try还是Catch执行,DROP TABLE命令都会执行。 请参阅:BOL Try...Catch

答案 1 :(得分:11)

您可以只声明一个表变量(在查询结束时会自动消失),而不是创建表。

BEGIN TRY
DECLARE @temp TABLE
(
    --columns
)
--do stuff
END TRY
BEGIN CATCH
--do other stuff
END CATCH

答案 2 :(得分:6)

没有等效的FINALLY 替代方案可能是表变量,但不完全相同,必须根据具体情况进行评估。
有一个SO question详细信息非常有用,可以做出明智的选择。
使用表变量,您不需要像使用临时表一样进行清理

答案 3 :(得分:0)

“ FINALLY”在功能上通常与(但不总是)与在TRY / CATCH(没有正式的“ FINALLY”块)之后跟随“ final”代码相同。如果情况不同,则TRY / CATCH块中的某些内容可能导致执行结束,例如return语句。

例如,我使用的一种模式是打开一个游标,然后将使用游标的代码放在TRY块中,然后在TRY / CATCH块之后关闭/释放游标。如果这些块不会退出正在执行的代码,这将很好地工作。但是,如果TRY CATCH块确实执行了RETURN(听起来像是个坏主意),如果 FINALLY块执行了,则将会被执行,但是按照T-SQL的要求,将“最终”代码放在TRY / CATCH之后,如果这些代码块导致执行结束,则将调用最终代码不会,可能会导致状态不一致

因此,虽然通常您可以将代码放在TRY / CATCH之后,但是如果这些块中的任何内容可以终止而不会进入清除代码,将是一个问题。

答案 4 :(得分:0)

SQL连接结束时,本地临时表(例如“ #Temp”)会自动删除。最好还是包含一个明确的DROP命令,但是如果不执行该命令,该表仍将被删除。

如果必须确保DROP尽快执行,则必须在CATCH子句中重复DROP命令,因为没有FINALLY:     -创建临时表;     开始尝试         -使用临时表;         -删除临时表;     结束尝试     开始比赛         -删除临时表;         扔; -重新抛出错误     结束观看

表变量是一种替代方法:当变量超出范围时将其删除。但是,表变量不支持统计信息,因此,如果表变量很大并且在多个查询中使用,则其性能可能不如临时表。

答案 5 :(得分:0)

使用自定义错误号表示没有真正的错误,只是最终代码?

-- create temp table;
BEGIN TRY
    -- use temp table;
    THROW 50555;
END TRY
BEGIN CATCH
    -- drop temp table;
    IF ERROR_NUMBER() <> 50555
        THROW;  -- rethrow the error
END CATCH

答案 6 :(得分:0)

这种情况下的正确答案是@Dave Bennett 提出的答案;在 TRY/CATCH 块之后检查表的存在并删除它。

但是,如果您从 CATCH 中引发异常并且需要进行一些“最终”类型处理怎么办?

会不会像在 CATCH 中设置一个变量并在您掉出 CATCH 后检查它一样简单?

DECLARE @is_error BIT = 0;

BEGIN TRY

  --Process data with other data sets

END TRY
BEGIN CATCH
  -- Your exception handling code here
  
  SET @is_error = 1;

END CATCH

-- Your "FINALLY" code here.

-- Then Check if you need to RAISERROR
IF @is_error = 0
BEGIN
    -- Your success code 
END
ELSE
BEGIN
    -- Your fail code
    -- RAISERROR
END;