Мы используем следующий шаблон обработки ошибок в хранимых процедурах 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, уровень 16, состояние 1, строка 30
Запрос ROLLBACK TRANSACTION не имеет соответствующей BEGIN TRANSACTION.
Почему исключение не обрабатывается? Пожалуйста помоги
ERROR_MESSAGE()
возвращает текст сообщения об ошибке, из-за которой был запущен блок CATCH конструкции TRY… CATCH. Возможно, что-то произошло ранее в стеке вызовов. . 11.05.2016catch
действительно работает правильно в вашей ситуации, но транзакция уже откатывается, когда достигаетсяcatch
блок? Затем в блокеcatch
снова вызываетсяrollback
, вызывая несоответствие количества транзакций. Не похоже, что вставка значения NULL в ненулевой столбец автоматически вызывает откат. Может быть, какие-то триггеры на целевых таблицах работаютrollback
при определенных условиях? 11.05.2016catch
вы делаетеrollback
безоговорочно. Если транзакция уже откатывается, это вызовет ошибку Запрос ROLLBACK TRANSACTION не имеет соответствующей ошибки BEGIN TRANSACTION.. Я думаю, что лучше использоватьif @@trancount > 0 rollback
(в предоставленной вами ссылке также используется этот шаблон). 12.05.2016