Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Транзакции в Ms SQL  [new]
Nihrom
Member

Откуда:
Сообщений: 2
Доброго времени суток.
У меня вопрос по принципу работы транзакций в MS SQL. Имеется вот такой код(он не претендует на правильность, важно понять что будет):
+ Собственно сам код

begin tran
delete TT from Town_and_Trips AS TT, Trips AS T where TT.Trp_code = T.Trp_code and T.P_code = @P_code
delete C from Costs AS C, Trips AS T where C.Trp_code = T.Trp_code and T.P_code = @P_code
delete from Trips where P_code = @P_code
delete from Personnel where P_code = @P_code
if @@ERROR = 0
commit tran
else
rollback tran
end

Теперь вопрос: Если при первом удалении произойдет какая-нибудь ошибка, транзакция будет отменена? Или же он продолжит выполнение следующих строк и при удачном последнем удалении по условию применит транзакцию?
P.S: Перечитал много разной информации но так нигде и не увидел явного ответа.
13 мар 14, 22:19    [15720576]     Ответить | Цитировать Сообщить модератору
 Re: Транзакции в Ms SQL  [new]
invm
Member

Откуда: Москва
Сообщений: 9845
Nihrom
Если при первом удалении произойдет какая-нибудь ошибка, транзакция будет отменена?
Пакет будет снят с выполнения и транзакция откатится автоматом если:
  • Произошла ошибка с severity >= 20 (также будет разорвано соединение с сервером и произведена запись об ошибке в журнал ОС)
  • Какая-либо инструкция инициировала срабатывание триггера, в котором явно выполнен rollback. В этом случае транзакция уже отменена и с выполнения снимается пакет.
  • Для сессии установлено xact_abort on и произошла run-time ошибка (не пользовательская)

    http://technet.microsoft.com/ru-ru/library/ms188790.aspx
    @@ERROR (Transact-SQL)

    Возвращает 0, если в предыдущей инструкции Transact-SQL не возникли ошибки.
    ...
    Поскольку функция @@ERROR очищается и сбрасывается для каждой выполняемой инструкции, проверяйте ее сразу после инструкции или сохраните значение в локальную переменную для последующей проверки.
  • 13 мар 14, 22:46    [15720683]     Ответить | Цитировать Сообщить модератору
     Re: Транзакции в Ms SQL  [new]
    Nihrom
    Member

    Откуда:
    Сообщений: 2
    invm, Спасибо за объяснение, вроде хорошо искал но про severity негде не видел.
    14 мар 14, 09:18    [15721784]     Ответить | Цитировать Сообщить модератору
     Re: Транзакции в Ms SQL  [new]
    AO_MMM
    Guest
    Nihrom,

    тогда уж лучше может так

    SET @facepalm = 0
    
    begin tran
    delete TT from Town_and_Trips AS TT, Trips AS T where TT.Trp_code = T.Trp_code and T.P_code = @P_code
    SET @facepalm = @facepalm + ABS(@@ERROR)
    
    delete C from Costs AS C, Trips AS T where C.Trp_code = T.Trp_code and T.P_code = @P_code
    SET @facepalm = @facepalm + ABS(@@ERROR)
    
    delete from Trips where P_code = @P_code
    SET @facepalm = @facepalm + ABS(@@ERROR)
    
    delete from Personnel where P_code = @P_code
    SET @facepalm = @facepalm + ABS(@@ERROR)
    
    if @facepalm = 0
    commit tran
    else 
    rollback tran
    end
    
    14 мар 14, 09:25    [15721814]     Ответить | Цитировать Сообщить модератору
     Re: Транзакции в Ms SQL  [new]
    invm
    Member

    Откуда: Москва
    Сообщений: 9845
    AO_MMM,

    Есть ли хоть какой-нибудь смысл в выполнении после ошибки последующих инструкций, если известно, что все равно результаты их действий придется откатить?
    14 мар 14, 09:30    [15721830]     Ответить | Цитировать Сообщить модератору
     Re: Транзакции в Ms SQL  [new]
    AO_MMM
    Member [заблокирован]

    Откуда:
    Сообщений: 27
    invm,

    Тогда так

    +
    SET @facepalm = 0
    
    begin tran
    delete TT from Town_and_Trips AS TT, Trips AS T where TT.Trp_code = T.Trp_code and T.P_code = @P_code
    SET @facepalm = @facepalm + ABS(@@ERROR)
    
    if @facepalm = 0
    delete C from Costs AS C, Trips AS T where C.Trp_code = T.Trp_code and T.P_code = @P_code
    SET @facepalm = @facepalm + ABS(@@ERROR)
    
    if @facepalm = 0
    delete from Trips where P_code = @P_code
    SET @facepalm = @facepalm + ABS(@@ERROR)
    
    if @facepalm = 0
    delete from Personnel where P_code = @P_code
    SET @facepalm = @facepalm + ABS(@@ERROR)
    
    if @facepalm = 0
    commit tran
    else 
    rollback tran
    end
    


    Лень было расставлять begin и end
    (подозреваю, что и без них будет то же самое, что и с ними).
    Да и хотелось сделать без GOTO
    14 мар 14, 09:38    [15721858]     Ответить | Цитировать Сообщить модератору
     Re: Транзакции в Ms SQL  [new]
    Ennor Tiegael
    Member

    Откуда:
    Сообщений: 3422
    Nihrom,

    Если хотя бы одной из этих таблиц не будет в базе, то батч будет отменен, но транзакция ОСТАНЕТСЯ ОТКРЫТОЙ. Very nasty.

    Особенно завораживающе выглядит в сочетании с транзакцией на клиенте и подавлением клиентским гуем сообщений об ошибках. У меня был такой случай однажды...
    14 мар 14, 09:44    [15721882]     Ответить | Цитировать Сообщить модератору
     Re: Транзакции в Ms SQL  [new]
    AO_MMM
    Member [заблокирован]

    Откуда:
    Сообщений: 27
    Ennor Tiegael
    Если хотя бы одной из этих таблиц не будет в базе


    Это совсем уж крайний случай.

    Может помочь EXECUTE('delete from ......')
    14 мар 14, 09:52    [15721912]     Ответить | Цитировать Сообщить модератору
     Re: Транзакции в Ms SQL  [new]
    invm
    Member

    Откуда: Москва
    Сообщений: 9845
    AO_MMM,

    Так тоже далеко не фонтан. Лучше и эффективнее set xact_abort on или try/catch.
    14 мар 14, 09:58    [15721938]     Ответить | Цитировать Сообщить модератору
     Re: Транзакции в Ms SQL  [new]
    dma_caviar
    Member

    Откуда: https://itproduct.ru
    Сообщений: 2361
    invm
    AO_MMM,

    Так тоже далеко не фонтан. Лучше и эффективнее set xact_abort on или try/catch.

    А лучше не "или", а "и"
    set xact_abort on
    declare @t int
    begin try
    
    ...
    
    	set @t = @@trancount
    	if @t = 0
    		begin transaction
    
    ...
    
    
    	if @t = 0
    		commit transaction
    end try
    begin catch
    	declare @m nvarchar(4000)
    	set @m = error_message()
    	if @t = 0 and @@trancount > 0
    		rollback transaction;
    
    	raiserror @m, 18, 1
    end catch;
    
    14 мар 14, 11:52    [15722734]     Ответить | Цитировать Сообщить модератору
     Re: Транзакции в Ms SQL  [new]
    invm
    Member

    Откуда: Москва
    Сообщений: 9845
    dma_caviar
    А лучше не "или", а "и"
    B как включение/выключение xact_abort повлияет на выполнение вашего кода?
    14 мар 14, 14:02    [15723930]     Ответить | Цитировать Сообщить модератору
     Re: Транзакции в Ms SQL  [new]
    dma_caviar
    Member

    Откуда: https://itproduct.ru
    Сообщений: 2361
    invm
    dma_caviar
    А лучше не "или", а "и"
    B как включение/выключение xact_abort повлияет на выполнение вашего кода?

    мда, xact_abort походу действительно лишнее
    я всегда думал что такие ошибки как например нарушение ссылочной целостности не прервут выполнение без xact_abort on
    14 мар 14, 15:55    [15725122]     Ответить | Цитировать Сообщить модератору
     Re: Транзакции в Ms SQL  [new]
    Mnior
    Member

    Откуда: Кишинёв
    Сообщений: 6724
    dma_caviar
    я всегда думал что такие ошибки как например нарушение ссылочной целостности не прервут выполнение без xact_abort on
    Плять, конечно не прервут, в случае без try/catch.

    Поэтому и было написано:
    invm
    Лучше и эффективнее set xact_abort on или try/catch.
    Отличительная особенность, что xact_abort не прерывает пользовательские ошибки типа RAISERROR, для этого используют THROW.
    C xact_abort просто не надо городить огород в коде.
    15 мар 14, 17:44    [15729554]     Ответить | Цитировать Сообщить модератору
    Все форумы / Microsoft SQL Server Ответить