У меня есть Insert
хранимая процедура, которая будет передавать данные, Table1
получать Column1
значение Table1
и вызывать вторую хранимую процедуру, которая будет кормить Table2.
Но когда я вызываю вторую хранимую процедуру как:
Exec USPStoredProcName
Я получаю следующую ошибку:
Счетчик транзакций после EXECUTE указывает на несовпадающее количество операторов BEGIN и COMMIT. Предыдущий счетчик = 1, текущий счетчик = 0.
Я прочитал ответы на другие подобные вопросы и не могу найти, где именно счетчик коммитов сбивается.
sql
sql-server-2012
sqlexception
Виньеш Кумар А
источник
источник
Ответы:
Если у вас есть блок TRY / CATCH, то вероятная причина в том, что вы перехватываете исключение прерывания транзакции и продолжаете. В блоке CATCH вы всегда должны проверять
XACT_STATE()
и обрабатывать соответствующие прерванные и нефиксируемые (обреченные) транзакции. Если ваш вызывающий абонент начинает транзакцию, а клиент попадает, скажем, в тупик (который прервал транзакцию), как вызываемый абонент будет сообщать вызывающему, что транзакция была прервана, и она не должна продолжать «обычную работу»? Единственный возможный способ - повторно вызвать исключение, заставив вызывающего абонента обработать ситуацию. Если вы молча проглатываете прерванную транзакцию, а вызывающий продолжает предполагать, что все еще находится в исходной транзакции, только беспредел может гарантировать (а ошибка, которую вы получаете, - это способ, которым движок пытается защитить себя).Я рекомендую вам перейти к обработке исключений и вложенным транзакциям, которые показывают шаблон, который можно использовать с вложенными транзакциями и исключениями:
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
источник
xact_abort on
?if @xstate = -1 rollback;
Глядя на этом примере MSDN , мы должны не откатить полную транзакцию , если не была не внешняя транзакция (то есть, если мы не делалиbegin tran
). Я думаю, что процедура должнаrollback
выполняться только в том случае, если мы начали транзакцию, что решит проблему @ sparrow.У меня тоже была эта пробема. Для меня причина была в том, что я делал
return commit
вместо того
commit return
в одной хранимой процедуре.
источник
Обычно это происходит, когда транзакция запущена и либо не зафиксирована, либо не откатывается.
В случае, если ошибка возникает в вашей хранимой процедуре, это может заблокировать таблицы базы данных, потому что транзакция не завершена из-за некоторых ошибок времени выполнения при отсутствии обработки исключений. Вы можете использовать обработку исключений, как показано ниже. УСТАНОВИТЬ XACT_ABORT
SET XACT_ABORT ON SET NoCount ON Begin Try BEGIN TRANSACTION //Insert ,update queries COMMIT End Try Begin Catch ROLLBACK End Catch
Источник
источник
Имейте в виду, что если вы используете вложенные транзакции, операция ROLLBACK откатывает все вложенные транзакции, включая самую внешнюю.
При использовании в сочетании с TRY / CATCH это может привести к описанной вами ошибке. Подробнее здесь .
источник
Это также может произойти, если ваша хранимая процедура обнаруживает сбой компиляции после открытия транзакции (например, таблица не найдена, недопустимое имя столбца).
Я обнаружил, что мне пришлось использовать 2 хранимые процедуры, одну «рабочую» и одну-оболочку с попыткой / уловом, обе с логикой, аналогичной описанной Ремусом Русану. Уловка рабочего используется для обработки «обычных» сбоев, а ловушка-оболочка для обработки ошибок сбоя компиляции.
https://msdn.microsoft.com/en-us/library/ms175976.aspx
Ошибки, на которые не влияет конструкция TRY… CATCH
Надеюсь, это поможет кому-то еще сэкономить несколько часов на отладке ...
источник
В моем случае ошибка была вызвана
RETURN
файломBEGIN TRANSACTION
. Так у меня было что-то вроде этого:Begin Transaction If (@something = 'foo') Begin --- do some stuff Return End commit
и это должно быть:
Begin Transaction If (@something = 'foo') Begin --- do some stuff Rollback Transaction ----- THIS WAS MISSING Return End commit
источник
Для меня после обширной отладки исправление было простой ошибкой; инструкция в catch после отката. Без этого уродливое сообщение об ошибке - вот что вы получите.
begin catch if @@trancount > 0 rollback transaction; throw; --allows capture of useful info when an exception happens within the transaction end catch
источник
У меня было такое же сообщение об ошибке, моя ошибка заключалась в том, что у меня была точка с запятой в конце строки COMMIT TRANSACTION
источник
Я столкнулся с этой ошибкой один раз после исключения этого оператора из своей транзакции.
COMMIT TRANSACTION [MyTransactionName]
источник
На мой взгляд, принятый ответ в большинстве случаев является излишним.
Причина ошибки часто заключается в несовпадении BEGIN и COMMIT, о чем ясно свидетельствует ошибка. Это означает использование:
Begin Begin -- your query here End commit
вместо того
Begin Transaction Begin -- your query here End commit
пропуск транзакции после начала вызывает эту ошибку!
источник
Убедитесь, что у вас нет нескольких транзакций в одной процедуре / запросе, одна или несколько из которых остались незавершенными.
В моем случае у меня случайно был оператор BEGIN TRAN в запросе
источник
Это также может зависеть от того, как вы вызываете SP из кода C #. Если SP возвращает какое-либо значение табличного типа, вызовите SP с помощью ExecuteStoreQuery, а если SP не возвращает никакого значения, вызовите SP с ExecuteStoreCommand
источник
Избегать использования
заявление, когда вы используете
BEGIN TRY ... END TRY BEGIN CATCH ... END CATCH
а также
BEGIN, COMMIT & ROLLBACK
операторы в хранимых процедурах SQL
источник
Если у вас есть структура кода вроде:
SELECT 151 RETURN -151
Затем используйте:
SELECT 151 ROLLBACK RETURN -151
источник