Где несоответствие Begin / Commit в этой хранимой процедуре? - PullRequest
0 голосов
/ 20 ноября 2010

Я получаю следующую ошибку:

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

Когда я пытаюсь выполнить эту хранимую процедуру:

create procedure [dbo].[SynchCustomerSubscriptions] (
  @subscriptions Subscriptions readonly )
as

begin transaction

begin tran SynchTransaction
  begin try
    delete s
    from Subscription s (nolock)
    where s.Customer in (
      select Customer
      from @subscriptions)
    exec AddSubscriptions
      @subscriptions
  end  try
  begin catch
    rollback tran SynchTransaction
    return
  end  catch
commit tran SynchTransaction

Кто-нибудь замечает проблему?

Ответы [ 3 ]

3 голосов
/ 20 ноября 2010
begin transaction 

begin tran SynchTransaction 

Иногда вы смотрите на это слишком долго, и самые простые вещи ускользают от вас.

0 голосов
/ 20 ноября 2010

Запуск транзакции с именем на самом деле очень плох в хранимых процедурах.Невозможно откатить только указанную транзакцию, как вы, очевидно, пытаетесь, если процедура вызывается внутри области действия другой транзакции, см. MSDN :

Имена нескольких транзакцийсерия вложенных транзакций с именем транзакции мало влияет на транзакцию.Только первое (самое внешнее) имя транзакции регистрируется в системе.Откат к любому другому имени (кроме действительного имени точки сохранения) приводит к ошибке.

То, что вы, вероятно, хотите, это точка сохранения, которая является другим типом зверя.Если вы хотите смешать вложенные транзакции, точки сохранения и блоки try / catch для исключений, все будет немного сложнее.Лучше использовать шаблон, подобный приведенному в этой статье Обработка исключений и вложенных транзакций , которая учитывает текущий @@TRANCOUNT и исключение 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) ;
        return;
    end catch   
end
0 голосов
/ 20 ноября 2010

Попробуйте это ...

create procedure [dbo].[SynchCustomerSubscriptions] (    
  @subscriptions Subscriptions readonly )    
as    

begin transaction SynchTransaction    

begin tran    
  begin try    
    delete s    
    from Subscription s (nolock)    
    where s.Customer in (    
      select Customer    
      from @subscriptions)    
    exec AddSubscriptions    
      @subscriptions    
  end  try    
  begin catch    
    rollback tran SynchTransaction    
    return    
  end  catch    
end tran
commit transaction SynchTransaction  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...