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

Откуда:
Сообщений: 839
есть таблица и к ней 2 триггера
+

CREATE TABLE [dbo].[Doc_Contracts] (
  [ID] int IDENTITY(1, 1) NOT NULL,
  [1CID] binary(16) NULL,
  [Number] varchar(20) COLLATE Cyrillic_General_CI_AS NULL,
  [DocDate] date NULL,
  [ObjectID] int NULL,
  [DirectionID] int NULL,
  [ClientID] int NULL,
  [ServicePercent] decimal(5, 2) NULL,
  [StartWork] date NULL,
  [FinishWork] date NULL,
  [DocSum] decimal(19, 2) NULL,
  [DocSumMeterials] decimal(19, 2) NULL,
  [DocFactSum] decimal(19, 2) NULL,
  [IsFinished] bit DEFAULT 0 NULL,
  [FactFinishDate] date NULL,
  [Note] varchar(150) COLLATE Cyrillic_General_CI_AS NULL,
  [DelMark] bit DEFAULT 0 NULL,
  [Posted] bit DEFAULT 0 NULL,
  [LastChange] datetime2(7) DEFAULT getdate() NULL,
  [CreateDate] datetime DEFAULT getdate() NULL,
  [UserName] varchar(100) COLLATE Cyrillic_General_CI_AS DEFAULT suser_sname() NULL,
  PRIMARY KEY CLUSTERED ([ID]),
  CONSTRAINT [Doc_Contracts_fk] FOREIGN KEY ([ObjectID]) 
  REFERENCES [dbo].[Spr_Objects] ([ID]) 
  ON UPDATE NO ACTION
  ON DELETE NO ACTION,
  CONSTRAINT [Doc_Contracts_fk2] FOREIGN KEY ([DirectionID]) 
  REFERENCES [dbo].[Spr_Directions] ([ID]) 
  ON UPDATE NO ACTION
  ON DELETE NO ACTION,
  CONSTRAINT [Doc_Contracts_fk4] FOREIGN KEY ([ClientID]) 
  REFERENCES [dbo].[Spr_Clients] ([ID]) 
  ON UPDATE NO ACTION
  ON DELETE NO ACTION
)
ON [PRIMARY]
GO

SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
GO

CREATE TRIGGER [dbo].[Doc_Contracts_tru2] ON [dbo].[Doc_Contracts]
WITH EXECUTE AS CALLER
FOR UPDATE
AS
BEGIN
  set dateformat dmy
  insert into Journal (ObjectType,id,EventType,LogStr)
  select 103,d.Id,2,
  case 
  	when 
  		isnull(d.Number,'')<>isnull(i.Number,'') then char(0)+'Number='+isnull(d.Number,'')+char(1)
    else ''
  end+  
  case 
  	when 
  		isnull(d.DocDate,'')<>isnull(i.DocDate,'') then char(0)+'DocDate='+isnull(convert(varchar(10),d.DocDate,103),'')+char(1)
    else ''
  end+ 
  case 
  	when 
  		isnull(d.ObjectID,'')<>isnull(i.ObjectID,'') then char(0)+'ObjectID='+isnull(cast(d.ObjectID as varchar),'')+char(1)
    else ''
  end+ 
  case 
  	when 
  		isnull(d.DirectionID,'')<>isnull(i.DirectionID,'') then char(0)+'DirectionID='+isnull(cast(d.DirectionID as varchar),'')+char(1)
    else ''
  end+ 
  case 
  	when 
  		isnull(d.ClientID,'')<>isnull(i.ClientID,'') then char(0)+'ClientID='+isnull(cast(d.ClientID as varchar),'')+char(1)
    else ''
  end+ 
  case 
  	when 
  		isnull(d.ServicePercent,'')<>isnull(i.ServicePercent,'') then char(0)+'ServicePercent='+isnull(cast(d.ServicePercent as varchar),'')+char(1)
    else ''
  end+
  case 
  	when 
  		isnull(d.StartWork,'')<>isnull(i.StartWork,'') then char(0)+'StartWork='+isnull(convert(varchar(10),d.StartWork,103),'')+char(1)
    else ''
  end+ 
  case 
  	when 
  		isnull(d.FinishWork,'')<>isnull(i.FinishWork,'') then char(0)+'FinishWork='+isnull(convert(varchar(10),d.FinishWork,103),'')+char(1)
    else ''
  end+ 
  case 
  	when 
  		isnull(d.DocSum,'')<>isnull(i.DocSum,'') then char(0)+'DocSum='+isnull(cast(d.DocSum as varchar),'')+char(1)
    else ''
  end+ 
  case 
  	when 
  		isnull(d.DocSumMeterials,'')<>isnull(i.DocSumMeterials,'') then char(0)+'DocSumMeterials='+isnull(cast(d.DocSumMeterials as varchar),'')+char(1)
    else ''
  end+ 
  case 
  	when 
  		isnull(d.DocFactSum,'')<>isnull(i.DocFactSum,'') then char(0)+'DocFactSum='+isnull(cast(d.DocFactSum as varchar),'')+char(1)
    else ''
  end+  
  case 
  	when 
  		isnull(d.IsFinished,'')<>isnull(i.IsFinished,'') then char(0)+'IsFinished='+isnull(cast(d.IsFinished as varchar),'')+char(1)
    else ''
  end+ 
  case 
  	when 
  		isnull(d.FactFinishDate,'')<>isnull(i.FactFinishDate,'') then char(0)+'FactFinishDate='+isnull(convert(varchar(10),d.FactFinishDate,103),'')+char(1)
    else ''
  end+  
  case 
  	when 
  		isnull(d.Note,'')<>isnull(i.Note,'') then char(0)+'Note='+isnull(d.Note,'')+char(1)
    else ''
  end+
  case 
  	when 
  		isnull(d.DelMark,'')<>isnull(i.DelMark,'') then char(0)+'DelMark='+isnull(cast(d.DelMark as varchar),'')+char(1)
    else ''
  end+ 
  case 
  	when 
  		isnull(d.Posted,'')<>isnull(i.Posted,'') then char(0)+'Posted='+isnull(cast(d.Posted as varchar),'')+char(1)
    else ''
  end    
  from deleted as d
  join inserted as i on i.id=d.id
  where isnull(d.Number,'')<>isnull(i.Number,'') or isnull(d.DocDate,'')<>isnull(i.DocDate,'') 
  or isnull(d.ObjectID,'')<>isnull(i.ObjectID,'') or isnull(d.ObjectID,'')<>isnull(i.ObjectID,'') 
  or isnull(d.DirectionID,'')<>isnull(i.DirectionID,'') or isnull(d.ClientID,'')<>isnull(i.ClientID,'')
  or isnull(cast(d.ServicePercent as varchar),'')<>isnull(cast(i.ServicePercent as varchar),'') or isnull(convert(varchar(10),d.StartWork,103),'')<>isnull(convert(varchar(10),i.StartWork,103),'') 
  
  or isnull(convert(varchar(10),d.FinishWork,103),'')<>isnull(convert(varchar(10),i.FinishWork,103),'') or isnull(cast(d.DocSum as varchar),'')<>isnull(cast(i.DocSum as varchar),'') 
  
  or isnull(cast(d.DocSumMeterials as varchar),'')<>isnull(cast(i.DocSumMeterials as varchar),'') or isnull(cast(d.DocFactSum as varchar),'')<>isnull(cast(i.DocFactSum as varchar),'')
 
  or isnull(d.IsFinished,'')<>isnull(i.IsFinished,'') or isnull(d.FactFinishDate,'')<>isnull(i.FactFinishDate,'') 
  or isnull(d.Note,'')<>isnull(i.Note,'') or isnull(d.DelMark,'')<>isnull(i.DelMark,'') 
  or d.Posted<>i.Posted 
  or isnull(d.Posted,'')<>isnull(i.Posted,'') 
END
GO

SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
GO

CREATE TRIGGER [dbo].[Doc_Contracts_tru] ON [dbo].[Doc_Contracts]
WITH EXECUTE AS CALLER
INSTEAD OF UPDATE
AS
BEGIN
  declare @id int
  declare @Lastchange datetime2
	select @id=id,@Lastchange=Lastchange from inserted
  if not exists(select id from Doc_Contracts where id=@id and Lastchange=@Lastchange) begin
  	select cast(1 as bit) iserror,'Документ отредактирован другим пользователем. Документ не сохранен. Закройте и откройте документ заново.'  mess
  	return
  end
  else begin
   	select cast(0 as bit) iserror 
    
		update dbs 
    set dbs.Number=i.Number,dbs.DocDate=i.DocDate,dbs.ObjectID=i.ObjectID,dbs.DirectionID=i.DirectionID,
        dbs.ClientID=i.ClientID,dbs.ServicePercent=i.ServicePercent,
        dbs.StartWork=i.StartWork,dbs.FinishWork=i.FinishWork,dbs.DocSum=i.DocSum,dbs.DocSumMeterials=i.DocSumMeterials,
        dbs.DocFactSum=i.DocFactSum,dbs.IsFinished=i.IsFinished,dbs.FactFinishDate=i.FactFinishDate,dbs.Note=i.Note,
        dbs.Posted=i.Posted,dbs.LastChange=getdate(),dbs.DelMark=i.DelMark

    from Doc_Contracts dbs
    join inserted i on i.id=dbs.id
    
  end
END
GO


один выполняется до обновления второй после...если отключить триггер который выполняется после - все норм...иначе ничего не записывается...причину нашел в конструкциях типа
  or isnull(d.IsFinished,'')<>isnull(i.IsFinished,'') 

если поле явно кастом преобразовать к стрингам то все норм
я так понимаю у этих триггеров одна транзакция? и почему может не срабатывать конструкция
  or isnull(d.IsFinished,'')<>isnull(i.IsFinished,'') 
?
22 мар 12, 13:10    [12294531]     Ответить | Цитировать Сообщить модератору
 Re: подскажите причину такого поведения в триггере  [new]
ther
Member

Откуда:
Сообщений: 839
sql server 2008 R2
22 мар 12, 13:12    [12294550]     Ответить | Цитировать Сообщить модератору
 Re: подскажите причину такого поведения в триггере  [new]
iap
Member

Откуда: Москва
Сообщений: 47145
Вместо этого
where isnull(d.Number,'')<>isnull(i.Number,'') or isnull(d.DocDate,'')<>isnull(i.DocDate,'') 
  or isnull(d.ObjectID,'')<>isnull(i.ObjectID,'') or isnull(d.ObjectID,'')<>isnull(i.ObjectID,'') 
  or isnull(d.DirectionID,'')<>isnull(i.DirectionID,'') or isnull(d.ClientID,'')<>isnull(i.ClientID,'')
  or isnull(cast(d.ServicePercent as varchar),'')<>isnull(cast(i.ServicePercent as varchar),'') or isnull(convert(varchar(10),d.StartWork,103),'')<>isnull(convert(varchar(10),i.StartWork,103),'') 
  
  or isnull(convert(varchar(10),d.FinishWork,103),'')<>isnull(convert(varchar(10),i.FinishWork,103),'') or isnull(cast(d.DocSum as varchar),'')<>isnull(cast(i.DocSum as varchar),'') 
  
  or isnull(cast(d.DocSumMeterials as varchar),'')<>isnull(cast(i.DocSumMeterials as varchar),'') or isnull(cast(d.DocFactSum as varchar),'')<>isnull(cast(i.DocFactSum as varchar),'')
 
  or isnull(d.IsFinished,'')<>isnull(i.IsFinished,'') or isnull(d.FactFinishDate,'')<>isnull(i.FactFinishDate,'') 
  or isnull(d.Note,'')<>isnull(i.Note,'') or isnull(d.DelMark,'')<>isnull(i.DelMark,'') 
  or d.Posted<>i.Posted 
  or isnull(d.Posted,'')<>isnull(i.Posted,'')
лучше написать это:
where not exists
(
 select d.Number,d.DocDate,d.ObjectID,d.DirectionID,d.ClientID,d.ServicePercent,d.StartWork,d.DocSum,d.DocSumMeterials,d.DocFactSum,d.IsFinished,d.FactFinishDate,d.Note,d.DelMark,d.Posted
 intersect
 select i.Number,i.DocDate,i.ObjectID,i.DirectionID,i.ClientID,i.ServicePercent,i.StartWork,i.DocSum,i.DocSumMeterials,i.DocFactSum,i.IsFinished,i.FactFinishDate,i.Note,i.DelMark,i.Posted
)
22 мар 12, 13:30    [12294695]     Ответить | Цитировать Сообщить модератору
 Re: подскажите причину такого поведения в триггере  [new]
iap
Member

Откуда: Москва
Сообщений: 47145
В CASEах - аналогично.
22 мар 12, 13:31    [12294713]     Ответить | Цитировать Сообщить модератору
 Re: подскажите причину такого поведения в триггере  [new]
invm
Member

Откуда: Москва
Сообщений: 9838
http://msdn.microsoft.com/en-us/library/ms191270.aspx
22 мар 12, 13:31    [12294717]     Ответить | Цитировать Сообщить модератору
 Re: подскажите причину такого поведения в триггере  [new]
ther
Member

Откуда:
Сообщений: 839
iap
спасибо попробую
invm
ну так для null в операция сравнения я использую isnull...там где нет то я уже просто пробовал и искал причину
22 мар 12, 13:35    [12294745]     Ответить | Цитировать Сообщить модератору
 Re: подскажите причину такого поведения в триггере  [new]
ther
Member

Откуда:
Сообщений: 839
самое обидное что полтора года назад делал проект на 2005 и проблем не было с такой конструкцией...все отлично работало
22 мар 12, 13:37    [12294769]     Ответить | Цитировать Сообщить модератору
 Re: подскажите причину такого поведения в триггере  [new]
invm
Member

Откуда: Москва
Сообщений: 9838
ther
ну так для null в операция сравнения я использую isnull...там где нет то я уже просто пробовал и искал причину
Да, проглядел.

А инстедный триггер у вас очень забавный...
22 мар 12, 13:38    [12294770]     Ответить | Цитировать Сообщить модератору
 Re: подскажите причину такого поведения в триггере  [new]
ther
Member

Откуда:
Сообщений: 839
invm
а чем забавный? дет я наговнокодил? ))
22 мар 12, 13:44    [12294837]     Ответить | Цитировать Сообщить модератору
 Re: подскажите причину такого поведения в триггере  [new]
Ken@t
Member

Откуда: 大地
Сообщений: 3265
ther
invm
а чем забавный? дет я наговнокодил? ))

  declare @id int
  declare @Lastchange datetime2
	select @id=id,@Lastchange=Lastchange from inserted
  if not exists(select id from Doc_Contracts where id=@id and Lastchange=@Lastchange) begin


угу, inserted - может быть N строк
22 мар 12, 13:45    [12294852]     Ответить | Цитировать Сообщить модератору
 Re: подскажите причину такого поведения в триггере  [new]
invm
Member

Откуда: Москва
Сообщений: 9838
ther
invm
а чем забавный? дет я наговнокодил? ))

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

Кстати, возврат наборов из триггеров грозятся запретить.
22 мар 12, 13:50    [12294904]     Ответить | Цитировать Сообщить модератору
 Re: подскажите причину такого поведения в триггере  [new]
iap
Member

Откуда: Москва
Сообщений: 47145
ther
invm
ну так для null в операция сравнения я использую isnull...там где нет то я уже просто пробовал и искал причину
ISNULL ( check_expression , replacement_value )
Типы возвращаемых данных
Возвращает тот же тип, что и у аргумента check_expression.

По поводу типа BIT. Вам так разве надо?
DECLARE @X BIT=NULL, @Y BIT=0, @Z BIT=1;
SELECT ISNULL(@X,'')[@X],ISNULL(@Y,'')[@Y],ISNULL(@Z,'')[@Z]
UNION ALL
SELECT @X,@Y,@Z;
22 мар 12, 13:54    [12294965]     Ответить | Цитировать Сообщить модератору
 Re: подскажите причину такого поведения в триггере  [new]
ther
Member

Откуда:
Сообщений: 839
аа...ну у меня вроде нет обновления целого стада записей...вроде

ну тогда я не буду переходить на новые версии...хм..как же тогда возвращать клиенту ошибку то
22 мар 12, 13:57    [12294998]     Ответить | Цитировать Сообщить модератору
 Re: подскажите причину такого поведения в триггере  [new]
ther
Member

Откуда:
Сообщений: 839
iap
пасиб..черт я был наивен...пора книжки читать(
22 мар 12, 13:59    [12295028]     Ответить | Цитировать Сообщить модератору
 Re: подскажите причину такого поведения в триггере  [new]
iap
Member

Откуда: Москва
Сообщений: 47145
ther
ну тогда я не буду переходить на новые версии...хм..
Это с чего вдруг?????!!
22 мар 12, 14:04    [12295073]     Ответить | Цитировать Сообщить модератору
 Re: подскажите причину такого поведения в триггере  [new]
invm
Member

Откуда: Москва
Сообщений: 9838
ther
хм..как же тогда возвращать клиенту ошибку то
Для этого есть raiserror.
22 мар 12, 14:17    [12295235]     Ответить | Цитировать Сообщить модератору
 Re: подскажите причину такого поведения в триггере  [new]
ther
Member

Откуда:
Сообщений: 839
iap
ther
ну тогда я не буду переходить на новые версии...хм..
Это с чего вдруг?????!!

та напугали этим
автор
Кстати, возврат наборов из триггеров грозятся запретить.
22 мар 12, 14:48    [12295622]     Ответить | Цитировать Сообщить модератору
 Re: подскажите причину такого поведения в триггере  [new]
ther
Member

Откуда:
Сообщений: 839
iap
спасибо вам огромное все работает...а то я гадина даже не поблагодарил
22 мар 12, 15:35    [12296039]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить