[英]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.