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