Счет транзакции после EXECUTE указывает несоответствующее число операторов BEGIN и COMMIT. Предыдущий счетчик = 1, текущий счетчик = 0
У меня есть встроенная хранимая процедура, которая будет подавать данные в таблицу1 и получать значение столбца 1 из таблицы 1 и вызывать вторую хранимую процедуру, которая будет подавать таблицу2.
Но когда я вызываю Вторую сохраненную процедуру как:
Exec USPStoredProcName
Это дает мне ошибку следующим образом:
Счет транзакции после EXECUTE указывает несоответствующее число операторов BEGIN и COMMIT. Предыдущий счетчик = 1, текущий счетчик = 0.
Я прочитал ответы в других подобных вопросах и не могу найти, где именно происходит перехват количества коммитов.
Ответы
Ответ 1
Если у вас есть блок TRY/CATCH, вероятной причиной является то, что вы перехватываете исключение транзакции и продолжаете. В блоке CATCH вы всегда должны проверять XACT_STATE()
и обрабатывать соответствующие прерванные и неконвертируемые (обреченные) транзакции. Если ваш вызывающий абонент начинает транзакцию, а calee хиты, скажем, тупика (который прервал транзакцию), как вызывающая сторона собирается связаться с вызывающим абонентом о том, что транзакция была прервана, и она не должна продолжаться "как обычно"? Единственный возможный способ - это воссоздать исключение, заставляя вызывающего абонента обрабатывать ситуацию. Если вы молча проглотите прерванную транзакцию, и вызывающий абонент продолжает считать, что все еще находится в исходной транзакции, может гарантировать только хаос (и ошибка, которую вы получаете, - это способ, которым движок пытается защитить себя).
Я рекомендую вам перейти Обработка исключений и вложенные транзакции, который показывает шаблон, который можно использовать с вложенными транзакциями и исключениями:
create procedure [usp_my_procedure_name]
as
begin
set nocount on;
declare @trancount int;
set @trancount = @@trancount;
begin try
if @trancount = 0
begin transaction
else
save transaction usp_my_procedure_name;
-- Do the actual work here
lbexit:
if @trancount = 0
commit;
end try
begin catch
declare @error int, @message varchar(4000), @xstate int;
select @error = ERROR_NUMBER(), @message = ERROR_MESSAGE(), @xstate = XACT_STATE();
if @xstate = -1
rollback;
if @xstate = 1 and @trancount = 0
rollback
if @xstate = 1 and @trancount > 0
rollback transaction usp_my_procedure_name;
raiserror ('usp_my_procedure_name: %d: %s', 16, 1, @error, @message) ;
end catch
end
go
Ответ 2
У меня тоже была эта проблема. Для меня причина в том, что я делал
return
commit
вместо
commit
return
в одной хранимой процедуре.
Ответ 3
Обычно это происходит, когда транзакция запущена и либо она не совершена, либо она не откат.
В случае ошибки в хранимой процедуре это может блокировать таблицы базы данных, поскольку транзакция не завершена из-за некоторых ошибок во время выполнения при отсутствии обработки исключений Вы можете использовать обработку исключений, как показано ниже. SET XACT_ABORT
SET XACT_ABORT ON
SET NoCount ON
Begin Try
BEGIN TRANSACTION
//Insert ,update queries
COMMIT
End Try
Begin Catch
ROLLBACK
End Catch
Источник
Ответ 4
Имейте в виду, что если вы используете вложенные транзакции, операция ROLLBACK возвращает все вложенные транзакции, в том числе внешние.
Это может при использовании в сочетании с TRY/CATCH привести к описанной вами ошибке. Подробнее здесь.
Ответ 5
Я столкнулся с этой ошибкой один раз после того, как я отклонил это выражение из моей транзакции.
COMMIT TRANSACTION [MyTransactionName]
Ответ 6
Это также может произойти, если ваша хранимая процедура обнаруживает сбой компиляции после открытия транзакции (например, таблица не найдена, недопустимое имя столбца).
Я обнаружил, что мне пришлось использовать 2 хранимых процедуры - "рабочий", а один - с try/catch с логикой, аналогичной описанной Ремусом Русану. Захват рабочего используется для обработки "нормальных" сбоев и обложек для обработки ошибок компиляции.
https://msdn.microsoft.com/en-us/library/ms175976.aspx
Ошибки, не затронутые TRY... Конструкция CATCH
Следующие типы ошибок не обрабатываются блоком CATCH , когда они происходят на одном уровне выполнения, как конструкция TRY... CATCH:
- Скомпилировать ошибки, такие как синтаксические ошибки, которые предотвращают запуск пакета.
- Ошибки, возникающие при перекомпиляции на уровне инструкций, такие как ошибки разрешения имен объектов, которые возникают после компиляции из-за отложенного разрешения имен.
Надеюсь, это поможет кому-то еще сохранить несколько часов отладки...
Ответ 7
Для меня после обширной отладки исправление было простым отсутствующим броском; в улове после откат. Без этого это уродливое сообщение об ошибке - это то, что вы в итоге получаете.
begin catch
if @@trancount > 0 rollback transaction;
throw; --allows capture of useful info when an exception happens within the transaction
end catch
Ответ 8
По-моему, принятый ответ в большинстве случаев является излишним.
Причиной ошибки часто является несоответствие BEGIN и COMMIT, как ясно указано в ошибке. Это означает использование:
Begin
Begin
-- your query here
End
commit
вместо
Begin Transaction
Begin
-- your query here
End
commit
исключение транзакции после Begin вызывает эту ошибку!
Ответ 9
У меня было такое же сообщение об ошибке, моя ошибка заключалась в том, что у меня была точка с запятой в конце строки COMMIT TRANSACTION
Ответ 10
Если у вас есть структура кода чего-то вроде:
SELECT 151
RETURN -151
Затем используйте:
SELECT 151
ROLLBACK
RETURN -151