Откат вообще не происходит ... почему? - PullRequest
2 голосов
/ 14 февраля 2011

У меня есть следующее

Declare @tbl Table(Id int identity, SomeCol varchar(10) not null)

Begin Transaction Tran1
   Declare @ErrorNum int  
   Declare @i int   
   Set @i =1

   --Start Operation
   While(@i <= 10)
    Begin

        If(@i = 9)
            Begin
                Insert into @tbl(SomeCol) Values(null)
                Set @ErrorNum = @@ERROR
            End
        Else
            -- All records will be inserted successfully
            Begin
                Insert into @tbl(SomeCol) Values(@i)
            End
        Set @i = @i +1

    End -- End of while

    -- If there is any error, notify that and roll back the transaction
   IF @ErrorNum <> 0 
   BEGIN 
      RAISERROR ('Attempt to insert null value in [Phone Number] is not allowed',16,1) 
      Rollback Transaction Tran1
   End
IF (@ErrorNum = 0)
   COMMIT TRANSACTION Tran1

   select * from @tbl

Я пытаюсь сделать следующее: если значение @i равно 9, я пытаюсь вставить нулевое значение в @tbl, что не должно допускатьвообще и должен откатить все записи и сгенерирует только пользовательское исключение.

Но это дает как системное, так и пользовательское исключение, и записи были вставлены и не откатаны, за исключением 9-й записи.

Ниже приведено то, что я получил на вкладке сообщений

**(1 row(s) affected)
(1 row(s) affected)
(1 row(s) affected)
(1 row(s) affected)
(1 row(s) affected)
(1 row(s) affected)
(1 row(s) affected)
(1 row(s) affected)
Msg 515, Level 16, State 2, Line 14
Cannot insert the value NULL into column 'SomeCol', table '@tbl'; column does not allow nulls. INSERT fails.
The statement has been terminated.
(1 row(s) affected)
Msg 50000, Level 16, State 1, Line 29
Attempt to insert null value in SomeCol is not allowed
(9 row(s) affected)**

А ниже - на вкладке "Записи"

Id  SomeCol
1   1
2   2
3   3
4   4
5   5
6   6
7   7
8   8
10  10

Я не уверен, что я сделал неправильно.

Требуется помощь.

Ответы [ 4 ]

2 голосов
/ 14 февраля 2011

Табличные переменные не возвращаются. Попробуйте вместо этого использовать таблицу #temporary, и ваш скрипт должен работать как положено!

create  Table #tbl(Id int identity, SomeCol varchar(10) not null)

Begin Transaction Tran1
   Declare @ErrorNum int  
   Declare @i int   
   Set @i =1

   --Start Operation
   While(@i <= 10)
    Begin

        If(@i = 9)
            Begin
                Insert into #tbl(SomeCol) Values(null)
                Set @ErrorNum = @@ERROR
            End
        Else
            -- All records will be inserted successfully
            Begin
                Insert into #tbl(SomeCol) Values(@i)
            End
        Set @i = @i +1

    End -- End of while

    -- If there is any error, notify that and roll back the transaction
   IF @ErrorNum <> 0 
   BEGIN 
      RAISERROR ('Attempt to insert null value in [Phone Number] is not allowed',16,1) 
      Rollback Transaction Tran1
   End
IF (@ErrorNum = 0)
BEGIN 
   PRINT 'COMMIT'
   COMMIT TRANSACTION Tran1
END
   select * from #tbl

drop table #tbl
0 голосов
/ 14 февраля 2011

Переменные таблицы нельзя откатить. Смотри здесь.

0 голосов
/ 14 февраля 2011

Если вы добавите следующее в начало вашего скрипта, тогда вся транзакция будет откатана при сбое (нет частично загруженной табличной переменной), но вы можете не увидеть свое сообщение об ошибке:

SET XACT_ABORT ON 

Из документации Microsoft :

Когда SET XACT_ABORT выключен, в некоторых случаях откатывается только оператор Transact-SQL, вызвавший ошибку, и транзакция продолжает обрабатываться.В зависимости от серьезности ошибки можно выполнить откат всей транзакции, даже если для SET XACT_ABORT установлено значение OFF.ВЫКЛ - настройка по умолчанию.

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

BEGIN TRY
    Declare @tbl Table(Id int identity, SomeCol varchar(10) not null)

    Begin Transaction Tran1
       Declare @i int   
       Set @i =1

       --Start Operation
       While(@i <= 10)
        Begin

            If(@i = 9)
                Begin
                    Insert into @tbl(SomeCol) Values(null)
                End
            Else
                -- All records will be inserted successfully
                Begin
                    Insert into @tbl(SomeCol) Values(@i)
                End
            Set @i = @i +1

        End -- End of while

        COMMIT TRANSACTION Tran1

       select * from @tbl
END TRY
BEGIN CATCH
       BEGIN 
          RAISERROR ('Attempt to insert null value in [Phone Number] is not allowed',16,1) 
          Rollback Transaction Tran1
       End
END CATCH
0 голосов
/ 14 февраля 2011

Похоже, что вы никогда не доберетесь до Rollback Transaction Tran1 - поскольку RAISE появляется раньше. Просто поменяйте местами обе строки

...