我们在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。
Msg 3903,Level 16,State 1,Line 30
ROLLBACK TRANSACTION请求没有相应的BEGIN TRANSACTION。
为什么不处理异常?请帮忙
答案 0 :(得分:1)
根据documentation(不受TRY ... CATCH Construct 部分影响的错误),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
以上代码生成
Msg 207,Level 16,State 1,Procedure #testSP _..._ 00053EAF,Line 33 列名称无效' somecolumn'。
Msg 266,Level 16,State 2,Procedure #testSP _..._ 00053EAF,Line 33 EXECUTE之后的事务计数表示不匹配的数量 BEGIN和COMMIT语句。先前的计数= 1,当前计数= 2.
正如您所见,尽管严重性级别为16,但未捕获错误并且不会打印消息Error happened
。
答案 1 :(得分:1)
如果您能够使用动态sql,则有一种方法,因此请尝试catch