簡體   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