Подтвердить что ты не робот

Счет транзакции после EXECUTE указывает несоответствующее число операторов BEGIN и COMMIT. Предыдущий счетчик = 1, текущий счетчик = 0

У меня есть встроенная хранимая процедура, которая будет подавать данные в таблицу1 и получать значение столбца 1 из таблицы 1 и вызывать вторую хранимую процедуру, которая будет подавать таблицу2.

Но когда я вызываю Вторую сохраненную процедуру как:

Exec USPStoredProcName

Это дает мне ошибку следующим образом:

Счет транзакции после EXECUTE указывает несоответствующее число операторов BEGIN и COMMIT. Предыдущий счетчик = 1, текущий счетчик = 0.

Я прочитал ответы в других подобных вопросах и не могу найти, где именно происходит перехват количества коммитов.

4b9b3361

Ответ 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