2010-11-19 11 views
0

Ich erhalte den folgenden Fehler:Wo ist der Begin/Commit-Konflikt in dieser gespeicherten Prozedur?

Transaktionsanzahl nach EXECUTE gibt eine nicht übereinstimmende Anzahl von BEGIN- und COMMIT-Anweisungen an. Vorherige Anzahl = 0, aktuelle Anzahl = 1

Wenn ich versuche, diese gespeicherte Prozedur auszuführen:

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 

Hat jemand das Problem vor Ort?

+0

Warum eine verschachtelte Transaktion in einer anderen mit, und begehen/rollbacking nur ein? Ich meine, wenn Sie sich verpflichten, committen Sie 'SynchTransaction', und wenn Sie ein Rollback durchführen, wird'SynchTransaction' zurückgesetzt, aber eine Transaktion bleibt, die unbenannte! Nur neugierig, etwas zu wissen und zu lernen. =) –

Antwort

3
begin transaction 

begin tran SynchTransaction 

Manchmal schauen Sie sich dieses Zeug zu lang an, und die einfachsten Dinge entgehen Ihnen.

+0

Ja, das war das Problem, danke! –

0

Try this ...

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

eine namens Transaktion zu beginnen ist eigentlich sehr schlecht innerhalb von gespeicherten Prozeduren. Es ist nicht möglich, nur die genannte Transaktion rückgängig zu machen, wie Sie offenbar versuchen, wenn das Verfahren in den Rahmen einer weiteren Transaktion aufgerufen wird, siehe 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.

Was möchten Sie wahrscheinlich ein Speicherpunkt ist, das ist eine andere Art von Biest. Wenn Sie geschachtelte Transaktionen, Savepoints und Exception Try/Catch-Blöcke mischen möchten, sind die Dinge etwas komplexer. Ist besser, ein Muster wie das von diesem Artikel verwenden Exception handling and nested transactions, die aktuelle @@TRANCOUNT und Ausnahme XACT_STATE hält:

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 
Verwandte Themen