2011-12-18 5 views
1

У меня есть две процедуры:TSQL сделки - фиксации и отката

create procedure P2 
as 
begin 
    print @@trancount 
    begin tran 

    if 1 = 1 
    begin 
      print @@trancount 
      rollback 
    end 
    else 
    begin 
      commit 
    end 
end 
go 


create procedure P1 
as 
begin 
    begin tran 
     print @@trancount 
     exec P2 
     print @@trancount 
    commit 
end 
go 

exec P1 

Когда я звоню P1 я получил:

1 
1 
2 
Msg 266, Level 16, State 2, Procedure P2, Line 0 
Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count = 1, current count = 0. 
0 
Msg 3902, Level 16, State 1, Procedure P1, Line 8 
The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION. 

Я ожидал, что результат, как этот:

1 
1 
2 
1 

Мои вопросы :

1. Why do I got this error? 

2. How should I write my procedure to do it good? 

ответ

3

Когда ваша процедура P2 выполняет линию rollback, вы откатываете транзакцию самого внешнего. (Тот, который первоначально был создан в P1). Это изменяет счет транзакции с момента, когда был вызван P2, пока он не был выполнен.

Если вы ожидаете, что процедура повлияет на количество транзакций, вы можете вызвать процедуру в Try-Catch, чтобы иметь возможность обрабатывать появившееся информационное сообщение.

От MSDN:

In stored procedures, ROLLBACK TRANSACTION statements without a savepoint_name 
or transaction_name roll back all statements to the outermost BEGIN TRANSACTION. 
A ROLLBACK TRANSACTION statement in a stored procedure that causes @@TRANCOUNT 
to have a different value when the stored procedure completes than the 
@@TRANCOUNT value when the stored procedure was called produces an informational 
message. This message does not affect subsequent processing. 

Вы также можете посмотреть статью на nesting transactions.

1
alter procedure P2 as 
    begin 
      print @@trancount 
       IF @@TRANCOUNT > 0 
         BEGIN 
          save tran SAVEPOINT1 
         END 
         ELSE 
         BEGIN 
         begin tran 
         END 
        if 1 = 1  
        begin 
          print @@trancount 
          IF XACT_STATE() <> -1 
          BEGIN 
           rollback tran SAVEPOINT1   
          END 

        end 
          else 
         begin 
         commit 
         end 
      end 
    go 
alter procedure P1 
    as 
    begin 
      begin tran 
      print @@trancount          
      exec P2  
      print @@trancount  
      commit 
    end 
go 
exec P1  
Смежные вопросы