Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 Корректная обработка ошибок или идеальная обёртка для ХП  [new]
_dodgy_
Member

Откуда:
Сообщений: 108
У кого-нибудь есть хороший шаблон для хранимых процедур, который бы вы использовали из проекта в проект?

У меня пока за время работы отполировался такой:

ALTER PROCEDURE [dbo].[spWrapDemo]
	@RunGUID varchar(50)
AS 
SET NOCOUNT ON
DECLARE @Result int

DECLARE @RecNum int, @ErrorId int, @ErrorMsg varchar(500), @Msg varchar(max)
SELECT @msg = '', @TranName = newid()

DECLARE @TranName varchar(50)
SAVE TRANSACTION @TranName

UPDATE [TableA] -- some dummy code
SET [id] = 1
WHERE [id] = 1/0
SELECT @RecNum = @@ROWCOUNT, @ErrorId = @@ERROR, @ErrorMsg = error_message()
IF @ErrorId <> 0 GOTO EXIT_BAD

-- AUDIT ------------------------
INSERT INTO [log] ([RunGUID],[Header],[Body])
SELECT @RunGUID, 'Procedure "spWrapDemo" - step 1.',
		'Time stamp: ' + [dbo].[sFormatTimeWithMilliseconds](getdate()) + 
		'; number of records updated: '+cast(@RecNum as varchar(50))+'. '
---------------------------------

GOTO EXIT_GOOD
EXIT_GOOD:
  SET @Result = 0
  COMMIT TRANSACTION
  SELECT @msg = @msg + 'SUCCESSFULL. COMMIT TRANSACTION was executed. Number of records updated at the last command: '+ cast(@RecNum as varchar(50))+'.'
  GOTO EXIT_POINT
EXIT_BAD:
  SET @Result = -1  
  ROLLBACK TRANSACTION @TranName
  SELECT @msg = @msg + 'FAILED. ROLLBACK TRANSACTION was executed. Error ID: ' + ISNULL(CAST(@ErrorId as varchar(50)),'-')+'; '+
	'Error Msg: "'+ISNULL(@ErrorMsg,'-')+'".'
  GOTO EXIT_POINT
EXIT_POINT:  
  INSERT INTO [log] ([header], [body])
  SELECT 
	'Procedure "spWrapDemo" - exit point.',
	'Message: '+@msg+''

  RETURN @Result 

Основные требования -
1) хранимые процедуры должны иметь возможность вызывать друг друга,
2) информация обо всём что произошло в вызванной процедуре (и в тех которые вызывает уже она) должна возвращаться в вызывающую (а не только целочисленное значение),
3) в случае ошибки, вызванная процедура должна откатить свою часть транзакции (см. SAVE TRANSACTION @TranName в коде) и вернуть сообщение об ошибке, вызывающая процедура сама будет решать откатывать ли общую (самую внешнюю) транзакцию или продолжить работу.

Пока нерешённые вопросы:

Стоит ли использовать TRY-CATCH?

Аудит (или трэйс) осуществляется посредством таблицы-лога. Чтобы потом можно было собрать все сообщения одной цепочки вызовов процедуры передают друг другу guid, записи идущие в лог помечаются с его помощью. В случае отката транзакции к сожалению записи из лога будут удалены - нельзя ли этого как-то избежать? Единственный выход который приходит на ум, это выбрать все записи в XML-переменную, откатить транзакци, а результат передать в вызывающую процедуру. Та добавит свои записи и откатит свою транзакцию и т.д. В итоге получится запись нечто вроде чёрного ящика.
27 май 11, 12:42    [10718848]     Ответить | Цитировать Сообщить модератору
 Re: Корректная обработка ошибок или идеальная обёртка для ХП  [new]
Гавриленко Сергей Алексеевич
Member

Откуда: Moscow
Сообщений: 37069
Шаблоны всплывают с некоторой периодичностью:
https://www.sql.ru/forum/actualtopics.aspx?search=%F8%E0%E1%EB%EE%ED&submit=%CD%E0%E9%F2%E8&bid=1
27 май 11, 12:43    [10718859]     Ответить | Цитировать Сообщить модератору
 Re: Корректная обработка ошибок или идеальная обёртка для ХП  [new]
pkarklin
Member

Откуда: Москва (Муром)
Сообщений: 74925
автор
В случае отката транзакции к сожалению записи из лога будут удалены - нельзя ли этого как-то избежать?


В MS SQL нет автономных транзакций. Можно их эмулировать через доп. коннект.

ЗЫ. Столько лишних операций... А обработки ошибок невидно.
ЗЫЗЫ. Не взлетит...
27 май 11, 12:48    [10718910]     Ответить | Цитировать Сообщить модератору
 Re: Корректная обработка ошибок или идеальная обёртка для ХП  [new]
Гавриленко Сергей Алексеевич
Member

Откуда: Moscow
Сообщений: 37069
И да, раз уж вы везде @@rowcount собираете, храните его в отдельном поле числом, чтобы когда захочется статистику посчитать, не пришлось бы мучительно и долго парсит ваш собственный лог.

_dodgy_
@ErrorMsg = error_message()
А ничего, что эту функцию надо в блоке catch вызывать?
27 май 11, 12:51    [10718952]     Ответить | Цитировать Сообщить модератору
 Re: Корректная обработка ошибок или идеальная обёртка для ХП  [new]
_dodgy_
Member

Откуда:
Сообщений: 108
Гавриленко Сергей Алексеевич
Шаблоны всплывают с некоторой периодичностью:
https://www.sql.ru/forum/actualtopics.aspx?search=%F8%E0%E1%EB%EE%ED&submit=%CD%E0%E9%F2%E8&bid=1

Эх, не догадался поискать по слову "шаблон". Спасибо за наводку.
27 май 11, 13:02    [10719066]     Ответить | Цитировать Сообщить модератору
 Re: Корректная обработка ошибок или идеальная обёртка для ХП  [new]
_dodgy_
Member

Откуда:
Сообщений: 108
Гавриленко Сергей Алексеевич
И да, раз уж вы везде @@rowcount собираете, храните его в отдельном поле числом, чтобы когда захочется статистику посчитать, не пришлось бы мучительно и долго парсит ваш собственный лог.

Да, парсинг нынешнего варианта лога уже доводит до бешенства. Там надо будет много полей держать. И скорее всего будут две таблицы - заголовков и записей.
А хранится будут не только результаты команд, но и сбор статистики до них и после них. Хоть и снижает скорость, но столько нервов экономит на отладке!

Гавриленко Сергей Алексеевич
_dodgy_
@ErrorMsg = error_message()
А ничего, что эту функцию надо в блоке catch вызывать?

То-то она не работает ;)
Спасибо.

Какой ваш-то шаблон?
27 май 11, 13:07    [10719107]     Ответить | Цитировать Сообщить модератору
 Re: Корректная обработка ошибок или идеальная обёртка для ХП  [new]
_dodgy_
Member

Откуда:
Сообщений: 108
Гавриленко Сергей Алексеевич
И да, раз уж вы везде @@rowcount собираете, храните его в отдельном поле числом, чтобы когда захочется статистику посчитать, не пришлось бы мучительно и долго парсит ваш собственный лог.


В аттаче - лог как он есть сейчас. В своё оправдание могу сказать что делался он на ходу, без всякого продумывания. Но даже в таком виде реально спасает.

К сообщению приложен файл. Размер - 74Kb
27 май 11, 13:20    [10719215]     Ответить | Цитировать Сообщить модератору
 Re: Корректная обработка ошибок или идеальная обёртка для ХП  [new]
pkarklin
Member

Откуда: Москва (Муром)
Сообщений: 74925
_dodgy_
В своё оправдание могу сказать что делался он на ходу, без всякого продумывания. Но даже в таком виде реально спасает.


В свое оправдание могу сказать, что при приводимой ниже нагрузке мне понадобится в 2а раза мощнее железо.

К сообщению приложен файл. Размер - 48Kb
27 май 11, 13:26    [10719258]     Ответить | Цитировать Сообщить модератору
 Re: Корректная обработка ошибок или идеальная обёртка для ХП  [new]
Maxx
Member [скрыт]

Откуда:
Сообщений: 24290
при наличие try catch использовать операторы безусловного перехода -ето точно лисапед,не взлетит
27 май 11, 14:18    [10719731]     Ответить | Цитировать Сообщить модератору
 Re: Корректная обработка ошибок или идеальная обёртка для ХП  [new]
_dodgy_
Member

Откуда:
Сообщений: 108
pkarklin
В свое оправдание могу сказать, что при приводимой ниже нагрузке мне понадобится в 2а раза мощнее железо.


Простите не понял...
28 май 11, 04:23    [10724016]     Ответить | Цитировать Сообщить модератору
Между сообщениями интервал более 1 года.
 Re: Корректная обработка ошибок или идеальная обёртка для ХП  [new]
баз лайтер
Member

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

аналогично, пытаясь зафиксировать универсальный паттерн, получил вот что -

create procedure /*PROCEDURE NAME*/
as 
begin
	declare @TRANCOUNT int
	declare @TRANNAME varchar(255)
	Select @TRANNAME = Convert(varchar(255),NEWID())

	Select @TRANCOUNT=@@TRANCOUNT

	IF (@TRANCOUNT=0)
		BEGIN TRANSACTION @TranName
	ELSE 
		SAVE TRANSACTION @TranName

	BEGIN TRY
		/*DO SOMETHING*/

		WHILE(@@TRANCOUNT > @TRANCOUNT)
			COMMIT TRANSACTION @TranName
	END TRY
	BEGIN CATCH
		Declare @ErrorMessage nvarchar(max)
		Declare @ErrorSeverity int
		Declare @ErrorState int

		Select @ErrorMessage = ERROR_MESSAGE()
			   ,@ErrorSeverity = ERROR_SEVERITY()
			   ,@ErrorState = ERROR_STATE()

                ---sometimes ERROR_STATE() returns 0
		if (@ErrorState = 0) Select @ErrorState = 1

		WHILE(@@TRANCOUNT > @TRANCOUNT) 
			ROLLBACK TRANSACTION @TranName

		RAISERROR(@ErrorMessage, @ErrorSeverity, @ErrorState) 
	END CATCH
end
GO


требования были -
  • не закрывать клиентскую (внешнюю) транзакцию
  • закрывать/откатывать транзакции, которые могут быть открыты внутри вызываемых процедур
  • возвращать всю информацию об ошибки клиенту

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

    оказалось, что процедура является (улучшенной) версией из книжки

    тестировалось на MSSQL 2005

    поругайте пожалуйста, и если кто знает почему ERROR_STATE() возвращает 0 - тоже сообщите.
  • 17 июл 12, 14:34    [12877976]     Ответить | Цитировать Сообщить модератору
     Re: Корректная обработка ошибок или идеальная обёртка для ХП  [new]
    step_ks
    Member

    Откуда:
    Сообщений: 936
    А номер ошибки клиенту совсем не нужен?
    17 июл 12, 14:46    [12878065]     Ответить | Цитировать Сообщить модератору
     Re: Корректная обработка ошибок или идеальная обёртка для ХП  [new]
    daw
    Member

    Откуда: Муром -> Москва
    Сообщений: 7381

    > и если кто знает почему ERROR_STATE() возвращает 0 - тоже сообщите.

    raiserror('error!', 16, 0)

    как минимум на 9.00.5000 уже вполне проходит.

    Posted via ActualForum NNTP Server 1.5

    17 июл 12, 14:48    [12878079]     Ответить | Цитировать Сообщить модератору
     Re: Корректная обработка ошибок или идеальная обёртка для ХП  [new]
    баз лайтер
    Member

    Откуда:
    Сообщений: 28
    select @@Version
    Microsoft SQL Server 2005 - 9.00.2047.00 (Intel X86)   Apr 14 2006 01:12:25   Copyright (c) 1988-2005 Microsoft Corporation  Express Edition on Windows NT 6.1 (Build 7601: Service Pack 1) 
    
    - недопустим пустой State в RAISERROR

    номер ошибки клиенту - переменная @@ERROR всмысле? в высшей степени дельное замечание
    17 июл 12, 15:25    [12878343]     Ответить | Цитировать Сообщить модератору
     Re: Корректная обработка ошибок или идеальная обёртка для ХП  [new]
    баз лайтер
    Member

    Откуда:
    Сообщений: 28
    которое обернулось нерешаемой задачей - тот код ошибки, который я получаю в CATCH, я не могу в RAISERROR использовать, только >50000. код ошибки теряется.
    17 июл 12, 16:13    [12878749]     Ответить | Цитировать Сообщить модератору
     Re: Корректная обработка ошибок или идеальная обёртка для ХП  [new]
    Mnior
    Member

    Откуда: Кишинёв
    Сообщений: 6723
    баз лайтер
    		WHILE(@@TRANCOUNT > @TRANCOUNT)
    			COMMIT TRANSACTION @TranName
    
    		WHILE(@@TRANCOUNT > @TRANCOUNT) 
    			ROLLBACK TRANSACTION @TranName
    
    Это шедевр.
    баз лайтер
    		Select @ErrorMessage = ERROR_MESSAGE()
    			   ,@ErrorSeverity = ERROR_SEVERITY()
    			   ,@ErrorState = ERROR_STATE()
    
    		RAISERROR(@ErrorMessage, @ErrorSeverity, @ErrorState) 
    
    Это бессмысленно. Не все ошибки возвращаете (они генерируются иногда пачками), итак потеряли ERROR_NUMBER, зачем вам тогда ERROR_STATE, это что мёртвому припарка.

    9.00.5000 > 9.00.2047
    Может обновиться?
    17 июл 12, 16:24    [12878863]     Ответить | Цитировать Сообщить модератору
     Re: Корректная обработка ошибок или идеальная обёртка для ХП  [new]
    Mnior
    Member

    Откуда: Кишинёв
    Сообщений: 6723
    баз лайтер
    которое обернулось нерешаемой задачей
    А на 2012 можно (THROW).
    17 июл 12, 16:27    [12878877]     Ответить | Цитировать Сообщить модератору
     Re: Корректная обработка ошибок или идеальная обёртка для ХП  [new]
    баз лайтер
    Member

    Откуда:
    Сообщений: 28
    	DECLARE @_tc INT, @_tn VARCHAR(255)
    	SELECT @_tc=@@TRANCOUNT
    	SELECT @_tn = CASE @_tc WHEN 0 THEN NULL ELSE CONVERT(VARCHAR(255),NEWID()) END
    	IF (@_tc=0) BEGIN TRANSACTION @_tn ELSE SAVE TRANSACTION @_tn
    	BEGIN TRY
    		---
    	WHILE(@@TRANCOUNT > @_tc) COMMIT TRANSACTION @_tn
    	END TRY
    	BEGIN CATCH
    		DECLARE @_em nvarchar(max),@_es int, @_st int
    		SELECT  @_em = ERROR_MESSAGE(),@_es = ERROR_SEVERITY(),@_st = ERROR_STATE()
    		/*2005*/IF (@_st = 0) SELECT @_st = 1
    		WHILE(@@TRANCOUNT > @_tc) ROLLBACK TRANSACTION @_tn
    		RAISERROR(@_em, @_es, @_st)
    	END CATCH
    
    то же самое, только при отсутствии внешней транзакции - все остальные тоже анонимные (и возвращается смысл оператору WHILE, который вас так насмешил)
    17 июл 12, 16:46    [12879076]     Ответить | Цитировать Сообщить модератору
     Re: Корректная обработка ошибок или идеальная обёртка для ХП  [new]
    Mnior
    Member

    Откуда: Кишинёв
    Сообщений: 6723
    Понравилось, хотим ещё, поэтому давайте вы нам раскажете "смысл" этого WHILE, с вашей точки зрения.
    17 июл 12, 19:16    [12880063]     Ответить | Цитировать Сообщить модератору
     Re: Корректная обработка ошибок или идеальная обёртка для ХП  [new]
    Mnior
    Member

    Откуда: Кишинёв
    Сообщений: 6723
    Хотя можно издеваться долго.
    Так что прочитайте тут.
    17 июл 12, 19:22    [12880079]     Ответить | Цитировать Сообщить модератору
     Re: Корректная обработка ошибок или идеальная обёртка для ХП  [new]
    Aleksey V.P.
    Member

    Откуда: Москва
    Сообщений: 575
    Не то что бы обработка ошибок, но вот такой шаблон на три основных операции с экземплярами данных.

    use [БД]
    go
    
    exec dbo.DevCreateOrReplaceObject @ObjectName = 'dbo.AED_Brand',
                                      @ObjectType = 'Procedure'
    go
    /* Сгенерировано на основе шаблона */
    /*
      Developer : [ФИО разработчика]
      Created   : [Дата]
      Purpose   : AED Бренда
      
    * HISTORY :
      [Дата], [ФИО разработчика]
        Меняем коды ошибок
    */
    /*
      Param definition :
        @ID                - Первичный ключ
        @BrandGroupID      - ID товарной группы
        @Name              - Наименование
        @Description       - Описание
        @ApprovedFlag      - Флаг утверждения
        @OriginalFlag	   - Орингинальный бренд или нет
        @Comment           - Коментарии    
        @DBErrorCode       - Код ошибки БД
        @DBErrorMessage    - Сообщение ошибки БД
        @DebugMode         - Режим отладки
                             0 - Нет режима отладки
                             1 - Режим отладки
        
      Result definition :	
        0  - Нет ошибки
        !0 - Ошибка
        -33 - Торговая марка не найдена
        -34 - Торговая марка не определена
        -35 - Торговая марка не уникальна
        -36 - Группа торговых марок определена неверно
    */
    alter procedure [dbo].[AED_Brand]
      @ID                int           = NULL OUTPUT,
      @BrandGroupID      int           = NULL,
      @Name              varchar(100)  = NULL,
      @Description       varchar(200)  = NULL,
      @ApprovedFlag      int           = NULL,  
      @OriginalFlag      int           = NULL,  
      @InPriceListFlag   int           = NULL,  
      @InCrossesFlag     int           = NULL,  
      @Comment           varchar(250)  = NULL,
      @DBErrorCode       int          = 0 OUTPUT,
      @DBErrorMessage    varchar(256) = '' OUTPUT,
      @DebugMode         int          = 0
    as
    begin
      declare
        @Res int,
        @_Date datetime
        
      /* ====================================================== */
      /* Подготовка параметров */
      /* ====================================================== */
      declare
        @_Name              varchar(100),
        @_Description       varchar(200),
        @_Comment           varchar(250),
    	  @_ApprovedFlag      int,
    	  @_OriginalFlag      int
    
      /* Определяем и чистим параметры */
      set @_Name = dbo.fDevPrepareString( @Name, 1)
      set @_Description = dbo.fDevPrepareString( @Description, 0)
      set @_Comment = dbo.fDevPrepareString( @Comment, 0)
      set @_ApprovedFlag = dbo.fDevPrepareFlag( @ApprovedFlag, 0)
      set @_OriginalFlag = dbo.fDevPrepareFlag( @OriginalFlag, 0)
    
      /* ====================================================== */
      /* Проверки */
      /* ====================================================== */
      /*  -33 - Торговая марка не найдена */
      if ( IsNull( @ID, 0) != 0)
      and NOT Exists( select
                        1
                      from dbo.Brands with (NoLock)
                      where ID = Abs( @ID))
      begin
        set @Res = -33
        goto Done
      end
      /*  -34 - Торговая марка не определена */
      if ( IsNull( @ID, 0) >= 0)
      and ( @_Name = '')
      begin
        set @Res = -34
        goto Done
      end
      /*  -35 - Торговая марка не уникальна */
      if ( IsNull( @ID, 0) >= 0)
      and Exists( select
                    1
                  from dbo.Brands with (NoLock)
                  where Name = @_Name
                    and ID != @ID)
      begin
        set @Res = -35
        goto Done
      end
      /*  -36 - Группа торговых марок определена неверно */
      if ( IsNull( @ID, 0) >= 0)
      and ( IsNull( @BrandGroupID, 0) != 0)
      and NOT Exists( select
                        1
                      from dbo.BrandGroups with (NoLock)
                      where ID = @BrandGroupID)
      begin
        set @Res = -36
        goto Done
      end
      
      /* ====================================================== */
      /* Подготовка данных */
      /* ====================================================== */
      /* .. */
      
      /* ====================================================== */
      /* Выполнение */
      /* ====================================================== */
      set @Res = 0
      
      begin try
        /* Add/Edit/Delete for dbo.Brands */
        if @DebugMode != 0
        begin
          set @_Date = GetDate()
          print 'Add/Edit/Delete for dbo.Brands'
        end
    
          if IsNull( @ID, 0) >= 0
          begin
            /* Add */
            if IsNull( @ID, 0) = 0
            begin
              if @DebugMode != 0
              begin
                print 'Add mode'
              end
              insert into dbo.Brands( BrandGroupID, 
                                      Name,
                                      [Description], 
                                      ApprovedFlag,
                                      OriginalFlag,
                                      Comment)
              values( @BrandGroupID,
                      @_Name, 
                      @_Description,
                      @_ApprovedFlag,
                      @_OriginalFlag,
                      @_Comment)
              set @ID = SCOPE_IDENTITY()                
            end
            /* Edit */
            else
            begin
              if @DebugMode != 0
              begin
                print 'Edit mode'
              end
    
              update dbo.Brands set
        		    BrandGroupID = @BrandGroupID,
                Name = @_Name,
                [Description] = @_Description,
                ApprovedFlag = @_ApprovedFlag,
                OriginalFlag = @_OriginalFlag,
                Comment = @_Comment,
                ChangeUser = SYSTEM_USER,
                ChangeDate = GetDate()
              where ID = @ID
            end
          end
          /* Delete */
          else
          begin
            /* Удаляем себя */
            if @DebugMode != 0
            begin
              print 'Delete mode'
            end
    
            delete from dbo.Brands
            where ID = Abs( @ID)
          end
        
        set @Res = @@ERROR
    
        if @DebugMode != 0
        begin
          print 'Время выполнения ' + Convert( varchar(10), DateDiff( ss, @_Date, GetDate()))
          print 'Результат выполнения ' + Convert( varchar(10), @Res)
        end
      end try
      begin catch
        set @Res = -100
        set @DBErrorCode = ERROR_NUMBER()
        set @DBErrorMessage = ERROR_MESSAGE()
      end catch 
    
      if @Res != 0
        goto Done
      
    Done:
    
      return @Res
    end
    /* Test samples
    /* Проверка выполнения */
    /* ADD Добавление */
    declare
      @Res int,
      @_ID int,
      @_BrandGroupID int,
      @_Name varchar(100),
      @_Description varchar(200),
      @_ApprovedFlag int,
      @_OriginalFlag int,
      @_Comment varchar(250),
      @_DBErrorCode int,
      @_DBErrorMessage varchar(256),
      @_DebugMode int
    
    set @_ID = NULL
    set @_BrandGroupID = NULL
    set @_Name = 'PUNKTEST'
    set @_Description = 'Punk Test'
    set @_ApprovedFlag = 1
    set @_OriginalFlag = 1
    set @_Comment = 'Тестирование dbo.AED_Brand'
    set @_DBErrorCode = 0
    set @_DBErrorMessage = NULL
    set @_DebugMode = 1
    
    exec @Res = AED_Brand  @ID = @_ID OUTPUT,
    							@BrandGroupID = @_BrandGroupID,
                                @Name = @_Name,
                                @Description = @_Description,
                                @ApprovedFlag = @_ApprovedFlag,
                                @OriginalFlag = @_OriginalFlag,
                                @Comment = @_Comment,
                                @DBErrorCode = @_DBErrorCode OUTPUT,
                                @DBErrorMessage = @_DBErrorMessage OUTPUT,
                                @DebugMode = @_DebugMode
    
    select
      @Res as ResultCode,
      dbo.fGetErrorMessage( @Res) as ResultMessage,
      @@TranCount as TranCount,
      @_DBErrorCode as DBErrorCode,
      @_DBErrorMessage as DBErrorMessage,
      @_ID as ObjectID
    
    /* Изменение Edit */  
    declare
      @Res int,
      @_ID int,
      @_BrandGroupID int,  
      @_Name varchar(100),
      @_Description varchar(200),
      @_ApprovedFlag int,
      @_OriginalFlag int,
      @_Comment varchar(250),
      @_DBErrorCode int,
      @_DBErrorMessage varchar(256),
      @_DebugMode int
    
    set @_ID = 19773
    set @_BrandGroupID = 2
    set @_Name = 'PUNKTEST01'
    set @_Description = 'Punk Test 01'
    set @_ApprovedFlag = 1
    set @_OriginalFlag = 1
    set @_Comment = 'Тестирование dbo.AED_Brand'
    set @_DBErrorCode = 0
    set @_DBErrorMessage = NULL
    set @_DebugMode = 1
    
    exec @Res = AED_Brand  @ID = @_ID OUTPUT,
    							@BrandGroupID = @_BrandGroupID,
                                @Name = @_Name,
                                @Description = @_Description,
                                @ApprovedFlag = @_ApprovedFlag,
                                @OriginalFlag = @_OriginalFlag,
                                @Comment = @_Comment,
                                @DBErrorCode = @_DBErrorCode OUTPUT,
                                @DBErrorMessage = @_DBErrorMessage OUTPUT,
                                @DebugMode = @_DebugMode
    
    select
      @Res as ResultCode,
      dbo.fGetErrorMessage( @Res) as ResultMessage,
      @@TranCount as TranCount,
      @_DBErrorCode as DBErrorCode,
      @_DBErrorMessage as DBErrorMessage,
      @_ID as ObjectID
    
    /* Удаление Delete */
    declare
      @Res int,
      @_ID int,
      @_DBErrorCode int,
      @_DBErrorMessage varchar(256),
      @_DebugMode int
      
    set @_ID = -19773
    set @_DBErrorCode = 0
    set @_DBErrorMessage = NULL
    set @_DebugMode = 1
    
    exec @Res = AED_Brand       @ID = @_ID,
                                @DBErrorCode = @_DBErrorCode OUTPUT,
                                @DBErrorMessage = @_DBErrorMessage OUTPUT,
                                @DebugMode = @_DebugMode
      
    select
      @Res as ResultCode,
      dbo.fGetErrorMessage( @Res) as ResultMessage,
      @@TranCount as TranCount,
      @_DBErrorCode as DBErrorCode,
      @_DBErrorMessage as DBErrorMessage,
      @_ID as ObjectID
    
    SQL запросы
    select * from dbo.Brands where Name = 'PUNKTEST01'
    select * from dbo.BrandGroups
    */
    go
    
    18 июл 12, 09:28    [12881637]     Ответить | Цитировать Сообщить модератору
     Re: Корректная обработка ошибок или идеальная обёртка для ХП  [new]
    баз лайтер
    Member

    Откуда:
    Сообщений: 28
    Aleksey V.P., спасибо! PUNK TEST PASSED

    смысл оператора WHILE для друзей из солнечной Молдавии:
    BEGIN Transaction
    BEGIN Transaction
    BEGIN Transaction
    COMMIT 
    select @@trancount --2 остались открытые транзакции
    WHILE(@@trancount>0)ROLLBACK
    select @@trancount --0 не осталось открытых транзакций
    
    18 июл 12, 14:19    [12883354]     Ответить | Цитировать Сообщить модератору
     Re: Корректная обработка ошибок или идеальная обёртка для ХП  [new]
    Aleksey V.P.
    Member

    Откуда: Москва
    Сообщений: 575
    баз лайтер
    Aleksey V.P., спасибо! PUNK TEST PASSED

    смысл оператора WHILE для друзей из солнечной Молдавии:
    BEGIN Transaction
    BEGIN Transaction
    BEGIN Transaction
    COMMIT 
    select @@trancount --2 остались открытые транзакции
    WHILE(@@trancount>0)ROLLBACK
    select @@trancount --0 не осталось открытых транзакций
    


    Достаточно один раз RollBack. Откатываются все транзакции.
    18 июл 12, 14:23    [12883386]     Ответить | Цитировать Сообщить модератору
     Re: Корректная обработка ошибок или идеальная обёртка для ХП  [new]
    step_ks
    Member

    Откуда:
    Сообщений: 936
    баз лайтер
    Aleksey V.P., спасибо! PUNK TEST PASSED

    смысл оператора WHILE для друзей из солнечной Молдавии:
    BEGIN Transaction
    BEGIN Transaction
    BEGIN Transaction
    COMMIT 
    select @@trancount --2 остались открытые транзакции
    WHILE(@@trancount>0)ROLLBACK
    select @@trancount --0 не осталось открытых транзакций
    

    А теперь уберите WHILE(@@trancount>0) , оставьте один ROLLBACK и посмотрите, изменится ли что.
    18 июл 12, 14:23    [12883390]     Ответить | Цитировать Сообщить модератору
     Re: Корректная обработка ошибок или идеальная обёртка для ХП  [new]
    баз лайтер
    Member

    Откуда:
    Сообщений: 28
    вы правы насчет ROLLBACK - независимо от того, сделан ли в процедуре SAVEPOINT или открыта новая транзакция - достаточно сделать откат один раз
    18 июл 12, 14:40    [12883538]     Ответить | Цитировать Сообщить модератору
    Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
    Все форумы / Microsoft SQL Server Ответить