2010-11-19 3 views
0

Я получаю сообщение об ошибке:Где находится несоответствие Begin/Commit в этой хранимой процедуре?

Счет транзакции после 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 

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

+0

Почему имея вложенную транзакцию внутри другого, и совершение/только один отката на предыдущую версию? Я имею в виду, что когда вы совершаете фиксацию, вы фиксируете «SynchTransaction», а когда вы откатываете, вы откатываете «SynchTransaction», но одна транзакция по-прежнему остается неназванной! Просто любопытно узнать и чему-то научиться. =) –

ответ

3
begin transaction 

begin tran SynchTransaction 

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

+0

Да, это была проблема, спасибо! –

0

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

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 
0

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

Naming multiple transactions in a series of nested transactions with a transaction name has little effect on the transaction. Only the first (outermost) transaction name is registered with the system. A rollback to any other name (other than a valid savepoint name) generates an error.

То, что вы, вероятно, хотите, точка сохранения, которая является другой вид зверя. Если вы хотите смешивать вложенные транзакции, точки сохранения и блоки try/catch исключений, все немного сложнее. Лучше всего использовать шаблон, как один из этой статьи Exception handling and nested transactions, которая рассматривает текущее @@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