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

Откуда:
Сообщений: 63
При переходе с 2000 на 2008 начали получать ошибку
Msg 3609, Level 16, State 1, Line 1
The transaction ended in the trigger. The batch has been aborted.

Почитав я понял что изменилось поведение триггеров. Но это бог с ним.
Биллинг у нас старый писали не мы, но сам триггер меня убил. Как я понимаю запись в таблицу не попадет никогда, и практика это подтверждает. Боле того в процедуре которая пытается писать в эту таблицу транзакция не объявляется. (все управление транзакциями снаружи и там после е вызова tcnm rollback)
В итоге заменил запись в таблицу insert into EAbort(Code,Message1) values(@ErrNo, @ErrStr).
на raiserror 50005 @ErrStr

Но мучает меня сомнение, вдруг я чего то не допонял и действия имеют смысл???
[src]USE [bill]
GO
/****** Object:  Trigger [dbo].[EAbortInsTrig]    Script Date: 01/14/2016 11:25:34 ******/
SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER OFF
GO
ALTER trigger [dbo].[EAbortInsTrig] on [dbo].[EAbort]
  for INSERT
  as
begin
  declare  @numrows int,
           @nullcnt int,
           @validcnt int,

           @errno   int,
           @errmsg  varchar(255)

  select @numrows = @@rowcount

-- Прикладная логика
select @errno = 50005
if @numrows <> 1
begin
    select  @errmsg = 'System error. Invalid usage of system EAbort table.'
	goto error
end

declare @Code int,
        @Message1 BCOMMENT

 select @Code = Code,
        @Message1 = Message1
   from Inserted

 select @errmsg = @Message1,
        @errno = @Code

error:
    raiserror @errno @errmsg
    rollback transaction
end


USE [bill]
GO
/****** Object:  StoredProcedure [dbo].[Abort]    Script Date: 01/14/2016 09:57:34 ******/
SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER OFF
GO

ALTER  proc [dbo].[Abort]
  @ErrNo int,
  @resourceName  BComment,
  @Param1 BComment = null,
  @Param2 BComment = null,
  @Param3 BComment = null,
  @Param4 BComment = null
as
begin
  declare @LangID BIDENT,
          @LangName BComment,
          @ErrStr BComment,
          @i int,
          @CurParam int


  select top 1

    @LangID = LangID from buser where bLogin = suser_sname ()
  if (@@error!=0) or (0=1)  goto Error

  select @LangID = isnull(@LangID,1)		

  if @LangID is not null
  begin
    select @ErrStr = MsgText
      from ResourceString sr,
           LangMessage lm
     where sr.Name       = @ResourceName
       and lm.ResourceID = sr.ID
       and lm.LangID     = @LangID
if @Param1 is not null
  begin
	select @ErrStr = @ErrStr + ' Вводимый IP адрес закреплен за договором  ' + @Param1
  end
if @Param2 is not null
  begin
	select @ErrStr = @ErrStr + '      В таблице hag_ip вводимый адрес закреплен за   ' + @Param2
  end

if @Param3 is not null
  begin
	select @ErrStr = @ErrStr + '  Вероятный IP адрес - ' + @Param3
  end


    if (@@error!=0) or (0=1)  goto Error
    if @ErrStr is null begin
      select @LangName = isnull(Name,'Unknown')  from Language where ID = @LangID
      if (@@error!=0) or (0=1)  goto Error
      select @ErrStr = @ResourceName--'Resource '''+@ResourceName+''' not found for language ' + @LangName
    end
    else begin -- Подстановка параметров в ErrStr
      select @i = 1,
             @CurParam = 1
      while @i < datalength (@ErrStr)
      begin
        if substring(@ErrStr,@i,2) = '%1'
        begin
          select @ErrStr = substring(@ErrStr,1,@i-1) + isnull(@Param1,'') + substring(@ErrStr,@i+2,255)
          select @i = @i+ datalength (@Param1)
        end
        else if substring(@ErrStr,@i,2) = '%2'
        begin
          select @ErrStr = substring(@ErrStr,1,@i-1) + isnull(@Param2,'') + substring(@ErrStr,@i+2,255)
          select @i = @i+ datalength (@Param2)
        end
        else if substring(@ErrStr,@i,2) = '%3'
        begin
          select @ErrStr = substring(@ErrStr,1,@i-1) + isnull(@Param3,'') + substring(@ErrStr,@i+2,255)
          select @i = @i+ datalength (@Param3)
        end
        else if substring(@ErrStr,@i,2) = '%4'
        begin
          select @ErrStr = substring(@ErrStr,1,@i-1) + isnull(@Param4,'') + substring(@ErrStr,@i+2,255)
          select @i = @i+ datalength (@Param4)
        end
        else begin
          select @i = @i + 1
        end
      end -- while
    end -- Конец подстановки параметров
  end
  else
    select @ErrStr = 'Cannot find language to display error message.'

  insert into EAbort(Code,Message1) values(@ErrNo, @ErrStr)

  return

Error:

  insert into EAbort(Code,Message1) values(43010, 'Error occured during execution of SQL. Cannot display a valid error message, because the language table is corrupt.')

end
14 янв 16, 08:33    [18676046]     Ответить | Цитировать Сообщить модератору
 Re: Rollback в триггере  [new]
Glory
Member

Откуда:
Сообщений: 104751
maldalik
Как я понимаю запись в таблицу не попадет никогда, и практика это подтверждает.

Запись в таблицу EAbort должна попадать при какой-то логической ошибке процедуры
Если таких ошибок не будет, то разумется в EAbort не будет записей
14 янв 16, 09:38    [18676229]     Ответить | Цитировать Сообщить модератору
 Re: Rollback в триггере  [new]
maldalik
Member

Откуда:
Сообщений: 63
Даже в случае ошибки ничего не запишется, в триггере всегда вызывается rollback
14 янв 16, 10:29    [18676527]     Ответить | Цитировать Сообщить модератору
 Re: Rollback в триггере  [new]
Glory
Member

Откуда:
Сообщений: 104751
maldalik
Даже в случае ошибки ничего не запишется, в триггере всегда вызывается rollback

Ну может return забыли поставить
14 янв 16, 10:46    [18676665]     Ответить | Цитировать Сообщить модератору
 Re: Rollback в триггере  [new]
maldalik
Member

Откуда:
Сообщений: 63
Если забыбли поставить return то что делает основное тело?
Переменные переприсваивает? Зачем?
14 янв 16, 10:49    [18676676]     Ответить | Цитировать Сообщить модератору
 Re: Rollback в триггере  [new]
Glory
Member

Откуда:
Сообщений: 104751
maldalik
Если забыбли поставить return то что делает основное тело?
Переменные переприсваивает? Зачем?

Вы предлагаете открыть филиал Ванги здесь ?
14 янв 16, 10:54    [18676721]     Ответить | Цитировать Сообщить модератору
 Re: Rollback в триггере  [new]
iap
Member

Откуда: Москва
Сообщений: 47052
maldalik
Если забыбли поставить return то что делает основное тело?
Переменные переприсваивает? Зачем?
Проверяет что-то и при ошибке - goto на rollback
14 янв 16, 10:56    [18676736]     Ответить | Цитировать Сообщить модератору
 Re: Rollback в триггере  [new]
iap
Member

Откуда: Москва
Сообщений: 47052
iap
maldalik
Если забыбли поставить return то что делает основное тело?
Переменные переприсваивает? Зачем?
Проверяет что-то и при ошибке - goto на rollback
Но влюбом случае показанный триггер - форменный урод.
Например, формат RAISERROR - древний, объявлен микрософтом устаревшим.
Обещано скоро запретить такой вызов (надо RAISERROR(параметры)).
Использование @@ROWCOUNT в триггере с некоторых пор некошерно, ибо неправильно отработает в MERGE.
Ну и нехорошо, вообще говоря, что он не позволяет обрабатывать более одной записи.
Про пропущенный RETURN уже говорили...
14 янв 16, 11:02    [18676765]     Ответить | Цитировать Сообщить модератору
 Re: Rollback в триггере  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 8350
Уберите rollback из триггера, goto выражение уберите и напишите обработчик TRY.
14 янв 16, 11:04    [18676780]     Ответить | Цитировать Сообщить модератору
 Re: Rollback в триггере  [new]
Glory
Member

Откуда:
Сообщений: 104751
iap
Обещано скоро запретить такой вызов (надо RAISERROR(параметры)).

Они "При переходе с 2000 на 2008 "

iap
Ну и нехорошо, вообще говоря, что он не позволяет обрабатывать более одной записи.

Эта таблица пользовательских _исключений_
По идеи исключения в нее должны попадать как раз по одному,а не скопом
14 янв 16, 11:05    [18676790]     Ответить | Цитировать Сообщить модератору
 Re: Rollback в триггере  [new]
maldalik
Member

Откуда:
Сообщений: 63
Владислав Колосов
Уберите rollback из триггера, goto выражение уберите и напишите обработчик TRY.

Я вообще убрал этот триггер нафиг.
А как правильно вызывать exception, если не Raiserror?
14 янв 16, 11:22    [18676943]     Ответить | Цитировать Сообщить модератору
 Re: Rollback в триггере  [new]
Glory
Member

Откуда:
Сообщений: 104751
maldalik
Я вообще убрал этот триггер нафиг.

А где бы вы держали лог исключений ?
14 янв 16, 11:24    [18676954]     Ответить | Цитировать Сообщить модератору
 Re: Rollback в триггере  [new]
maldalik
Member

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

А зачем нужен лог исключений в таком виде?
Только код ошибки и описание, без описнаия времени пользователя и других подробностей?

База много лет работала без него, следовательно нужды в нем нет. У нас давно сделаны свои логи, но иногда натыкаемся вот на такие мундштуки и репу чешем...
14 янв 16, 11:42    [18677119]     Ответить | Цитировать Сообщить модератору
 Re: Rollback в триггере  [new]
Glory
Member

Откуда:
Сообщений: 104751
maldalik
А зачем нужен лог исключений в таком виде?

В каком "таком" ? В вашей системе есть описание того, что должен представлять из себя лог пользовательских исключений ?

maldalik
База много лет работала без него, следовательно нужды в нем нет.

Этот код вообще тестировал кто-то ? Для него есть документация ?

maldalik
У нас давно сделаны свои логи, но иногда натыкаемся вот на такие мундштуки и репу чешем...

Если вы проводите ревизию системы 20ти летней давности, то зачем справшивать непричастных людей о мотивах ее создателей ?
14 янв 16, 11:50    [18677190]     Ответить | Цитировать Сообщить модератору
 Re: Rollback в триггере  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
iap
iap
пропущено...
Проверяет что-то и при ошибке - goto на rollback
Но влюбом случае показанный триггер - форменный урод.
Например, формат RAISERROR - древний, объявлен микрософтом устаревшим.
Обещано скоро запретить такой вызов (надо RAISERROR(параметры)).

Использование @@ROWCOUNT в триггере с некоторых пор некошерно, ибо неправильно отработает в MERGE.
Ну и нехорошо, вообще говоря, что он не позволяет обрабатывать более одной записи.
Про пропущенный RETURN уже говорили...


Он уже запрещен в SQL Server 2012
14 янв 16, 11:57    [18677238]     Ответить | Цитировать Сообщить модератору
 Re: Rollback в триггере  [new]
maldalik
Member

Откуда:
Сообщений: 63
Winnipuh
Он уже запрещен в SQL Server 2012

Странно в msdn для 2014 вполне себе жив
https://msdn.microsoft.com/ru-ru/library/ms178592(v=sql.120).aspx
14 янв 16, 12:04    [18677275]     Ответить | Цитировать Сообщить модератору
 Re: Rollback в триггере  [new]
Glory
Member

Откуда:
Сообщений: 104751
maldalik
Странно в msdn для 2014 вполне себе жив
https://msdn.microsoft.com/ru-ru/library/ms178592(v=sql.120).aspx

RAISERROR и RAISERROR() - это разные инструкции
14 янв 16, 12:06    [18677284]     Ответить | Цитировать Сообщить модератору
 Re: Rollback в триггере  [new]
iap
Member

Откуда: Москва
Сообщений: 47052
maldalik
Winnipuh
Он уже запрещен в SQL Server 2012

Странно в msdn для 2014 вполне себе жив
https://msdn.microsoft.com/ru-ru/library/ms178592(v=sql.120).aspx
Так работает?
RAISERROR 50000 'Ошибка';
14 янв 16, 12:11    [18677318]     Ответить | Цитировать Сообщить модератору
 Re: Rollback в триггере  [new]
maldalik
Member

Откуда:
Сообщений: 63
И еще вопрос как правильно переписать такой триггер?
Он должен обламывать удаление клиента если он существует давно.
Как я понимаю Rollback для 2008 не вариант
USE [bill]
GO
/****** Object:  Trigger [dbo].[Subscriber_d]    Script Date: 01/14/2016 15:12:30 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:		<Author,,Name>
-- Create date: <Create Date,,>
-- Description:	<Description,,>
-- =============================================
ALTER TRIGGER [dbo].[Subscriber_d]
      ON  [dbo].[Subscriber]   
   AFTER DELETE
AS 
BEGIN
	-- SET NOCOUNT ON added to prevent extra result sets from
	-- interfering with SELECT statements.
	SET NOCOUNT ON;
	If (select datediff(m,contrdate,getdate()) from deleted)>2
	Begin
	print 'Нельзя удалить клиентов,существующих более 2 месяцев'
	rollback
	goto end_
	End 
	Insert into Subscriber_del
	select ID, getdate()
	from deleted
	end_:
    -- Insert statements for trigger here

END
14 янв 16, 12:14    [18677347]     Ответить | Цитировать Сообщить модератору
 Re: Rollback в триггере  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
можно instead of использовать
14 янв 16, 12:16    [18677360]     Ответить | Цитировать Сообщить модератору
 Re: Rollback в триггере  [new]
Glory
Member

Откуда:
Сообщений: 104751
maldalik
И еще вопрос как правильно переписать такой триггер?

Во-первых, триггер либо должен уметь обрабатывать множество записей, либо единичную запись. А у вас ни то ни то
Во-вторых, есть instead триггера
В-третьих, что такое "Rollback для 2008 не вариант" ?
14 янв 16, 12:18    [18677391]     Ответить | Цитировать Сообщить модератору
 Re: Rollback в триггере  [new]
iap
Member

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

с 2 сравнивать нельзя, если одним DELETEом удаляют больше одной записи.
Поскольку количество записей не проверяете на равенство 1, то всё неправильно.
Почему не можете обращаться с deleted как с множеством?
14 янв 16, 12:19    [18677397]     Ответить | Цитировать Сообщить модератору
 Re: Rollback в триггере  [new]
maldalik
Member

Откуда:
Сообщений: 63
iap
maldalik
пропущено...

Странно в msdn для 2014 вполне себе жив
https://msdn.microsoft.com/ru-ru/library/ms178592(v=sql.120).aspx
Так работает?
RAISERROR 50000 'Ошибка';

в 2008 работает, но понял разницу выше Glory указал.
14 янв 16, 12:21    [18677411]     Ответить | Цитировать Сообщить модератору
 Re: Rollback в триггере  [new]
maldalik
Member

Откуда:
Сообщений: 63
Glory
maldalik
И еще вопрос как правильно переписать такой триггер?

Во-первых, триггер либо должен уметь обрабатывать множество записей, либо единичную запись. А у вас ни то ни то
Во-вторых, есть instead триггера
В-третьих, что такое "Rollback для 2008 не вариант" ?


по первому по ходу косяк. Но в общем нивелируемый логикой приложения массовое удаление в интерфейсе отстутсвует.
вторые буду изучать.
по отретьему rollback в триггере вызывает ошибку в 2008
14 янв 16, 12:26    [18677458]     Ответить | Цитировать Сообщить модератору
 Re: Rollback в триггере  [new]
iap
Member

Откуда: Москва
Сообщений: 47052
maldalik
Glory
пропущено...

Во-первых, триггер либо должен уметь обрабатывать множество записей, либо единичную запись. А у вас ни то ни то
Во-вторых, есть instead триггера
В-третьих, что такое "Rollback для 2008 не вариант" ?


по первому по ходу косяк. Но в общем нивелируемый логикой приложения массовое удаление в интерфейсе отстутсвует.
вторые буду изучать.
по отретьему rollback в триггере вызывает ошибку в 2008
Не ошибку, а warning
14 янв 16, 12:27    [18677471]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2 3   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить