繁体   English   中英

SQL Server 中的 Try/Catch 块不处理错误

[英]Errors are not handled by Try/Catch Block in SQL Server

我们在 SQL Server 存储过程中使用以下错误处理模式:

ALTER PROCEDURE [dbo].[USP_Districtdata_Import]
    @DistrictData DistrictData Readonly
AS
BEGIN
    SET NOCOUNT ON;
    BEGIN TRY
    BEGIN TRAN

    --Insert the new records into BudgetDistrict Table.
    INSERT INTO [dbo].[BudgetDistrict]
    (
     DistrictID,
     [Year],
     Season,
     BudgetStateID,
     ProjectedReturnCountIsCalc,
     RowStatus,
     CreatedBy,
     CreatedDate,
     LastModifiedBy,
     LastModifiedDate,
     EnableBudgetLock
     )

    SELECT
    DISTINCT list.[District Id],list.[Year],list.[Season],1,0,'A',@CreatedBy,@Updtime,@CreatedBy,@Updtime,0
    FROM @DistrictData liston]
        AND bud.RowStatus = 'A'
        )
    LEFT OUTER JOIN [dbo].[BudgetDistrict] bud
      ON (bud.DistrictID  = list.[District Id]
        AND bud.[Year]    = list.[Year]
        AND bud.[Season]  = list.[Seas
    WHERE bud.DistrictID IS NULL


    --Update the existing pending budgets
    UPDATE wk
    SET  wk.Budget         = list.[Budget], 
         wk.BudgetAdjusted = list.[Budget],
         wk.ProjectedReturnCount = list.[ProjectedReturn Count], 
         wk.CreatedBy      = @CreatedBy, 
         wk.CreatedDate    = @Updtime,
         wk.LastModifiedBy = @CreatedBy, 
         wk.LastModifiedDate = @Updtime  
    FROM @DistrictData list
    INNER JOIN [dbo].[BudgetDistrict] bud
      ON (bud.DistrictID  = list.[District Id]
        AND bud.[Year]    = list.[Year]
        AND bud.[Season]  = list.[Season])
    INNER JOIN [dbo].[BudgetDistrictWeekly] wk
      ON (wk.NationalBudgetID = bud.BudgetDistrictID
       AND wk.[WeekDate]      = list.[Week])
    WHERE bud.RowStatus  = 'A'
       AND wk.RowStatus  = 'A'
       AND bud.BudgetStateID = 1

    --Insert the new budgets
    INSERT INTO [dbo].[BudgetDistrictWeekly]
    (
    WeekDate,
    Budget,
    BudgetAdjusted,
    RowStatus,
    CreatedBy,
    CreatedDate,
    LastModifiedBy,
    LastModifiedDate,
    ProjectedReturnCount
    )

    SELECT LIST.[Week],list.[Budget],list.[Budget],'A',@CreatedBy,@Updtime,@CreatedBy,@Updtime,[ProjectedReturn Count]
    FROM @DistrictData list
    LEFT JOIN [dbo].[BudgetDistrict] bud
      ON (bud.DistrictID  = list.[District Id]
        AND bud.[Year]    = list.[year]
        AND bud.[Season]  = list.Season
        AND bud.RowStatus = 'A')
    WHERE bud.DistrictID IS NULL

       IF @@ERROR = 0
       BEGIN
              COMMIT TRAN;
      END
    END TRY
    BEGIN CATCH
        SELECT 
            ERROR_NUMBER() AS ErrorNumber,  
            ERROR_LINE() AS ErrorLine, 
            ERROR_MESSAGE() AS ErrorMessage;
        ROLLBACK TRAN;
    END CATCH

SET NOCOUNT OFF;
END

但是当存储过程中出现以下错误时,try/catch 块不起作用。

错误详细信息:存储过程试图将NULL值插入到非空列中。

在执行存储过程期间,出现以下错误

EXECUTE 之后的事务计数表示 BEGIN 和 COMMIT 语句的数量不匹配。 先前计数 = 1,当前计数 = 0。

消息 3903,级别 16,状态 1,第 30 行
ROLLBACK TRANSACTION 请求没有对应的 BEGIN TRANSACTION。

为什么不处理异常? 请帮忙

根据文档错误不受 TRY…CATCH 构造部分的影响),某些错误不会被 CATCH 语句捕获。

特别是:

  • 阻止批处理运行的编译错误,例如语法错误。
  • 语句级重编译过程中出现的错误,例如由于名称解析延迟导致编译后出现对象名称解析错误。

非常典型的情况是当存储过程访问在创建存储过程后删除的表列(或访问对象)时。

请参阅下面的示例:

create table #test (id int, somecolumn uniqueidentifier)
GO
create procedure #testSP
as
begin try
    set nocount on;

    begin tran;

    insert into #test (id, somecolumn)
    values (1, 0x);

    commit;

end try
begin catch
    rollback;
    print 'Error happened';
end catch
GO
exec #testSP
GO
alter table #test
    drop column somecolumn
GO
exec #testSP
GO

上面的代码产生

消息 207,级别 16,状态 1,过程#testSP_..._00053EAF,第 33 行无效的列名称“somecolumn”。

消息 266,级别 16,状态 2,过程#testSP_..._00053EAF,第 33 行 EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数量不匹配。 先前计数 = 1,当前计数 = 2。

如您所见,尽管严重性级别为 16,但未捕获Error happened并且未打印Error happened消息。

有一种方法,如果您能够使用动态 sql,那么请尝试使用 catch 工作

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM