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

Откуда:
Сообщений: 734
Конструкция IF UPDATE(поле) в триггере выдает ошибку, если нё запихнуть в переменную (строку), а потом выполнить ее через exec

Вот кусок триггера:
 set @SQL2= N'IF UPDATE('+@CURR_FIELD+')
               begin
               set  @SPISOK_IZM_POLEY=(
                         case 
                              when @SPISOK_IZM_POLEY='''' then @CURR_FIELD
                              when @SPISOK_IZM_POLEY<>'''' then @SPISOK_IZM_POLEY+'', ''+@CURR_FIELD
                         end)
               end'
          exec sp_executesql @SQL2, N'@SPISOK_IZM_POLEY bit out, @CURR_FIELD varchar(max)', @SPISOK_IZM_POLEY=@SPISOK_IZM_POLEY out, @CURR_FIELD=@CURR_FIELD
     

ошибка:
автор
Msg 140, Level 15, State 1, Line 1
Can only use IF UPDATE within a CREATE TRIGGER statement.
19 сен 11, 10:32    [11296459]     Ответить | Цитировать Сообщить модератору
 Re: конструкция IF UPDATE(поле) в триггере  [new]
Glory
Member

Откуда:
Сообщений: 104751
И что вам непонятно из текста сообщения ?
19 сен 11, 10:34    [11296469]     Ответить | Цитировать Сообщить модератору
 Re: конструкция IF UPDATE(поле) в триггере  [new]
nerv
Member

Откуда:
Сообщений: 734
так конструкция итак находится в теле триггера
19 сен 11, 10:39    [11296498]     Ответить | Цитировать Сообщить модератору
 Re: конструкция IF UPDATE(поле) в триггере  [new]
Glory
Member

Откуда:
Сообщений: 104751
nerv
так конструкция итак находится в теле триггера

Она находится в теле sp_executesql
19 сен 11, 10:40    [11296504]     Ответить | Цитировать Сообщить модератору
 Re: конструкция IF UPDATE(поле) в триггере  [new]
nerv
Member

Откуда:
Сообщений: 734
стромозил, простите, видимо правильнее будет:

IF UPDATE (поле)
BEGIN
SET
EXEC
END
19 сен 11, 10:44    [11296525]     Ответить | Цитировать Сообщить модератору
 Re: конструкция IF UPDATE(поле) в триггере  [new]
nerv
Member

Откуда:
Сообщений: 734
проблема только в том, что имя поля задается не явно, а в курсоре, а описанная выше конструкция не проходит...
19 сен 11, 10:47    [11296549]     Ответить | Цитировать Сообщить модератору
 Re: конструкция IF UPDATE(поле) в триггере  [new]
Glory
Member

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

Не в курсоре, а за пределами триггера

ЗЫ
Создаете универсальный триггер ?
19 сен 11, 10:49    [11296561]     Ответить | Цитировать Сообщить модератору
 Re: конструкция IF UPDATE(поле) в триггере  [new]
nerv
Member

Откуда:
Сообщений: 734
нет, в триггере - курсор, в котором список полей... вот кусок кода:
declare @PATIENTID int, @ID int, @FIELDS varchar(max), @FIELDS_COUNT int, @SQL varchar(max), @USER_ID int, @LAST_NLINE int, @NOW varchar(100)
set @USER_ID = (select [USER_ID] from dbo.KRN_SYS_SESSIONS where SESSION_ID = @@SPID)
set @NOW = '''' + convert(varchar(100), getdate(), 120) + ''''
-- Находим список общих полей без полей, определяющих кто/когда создал ЭТУ запись
set @FIELDS = stuff((
select ',' + t1.Column_Name
from INFORMATION_SCHEMA.COLUMNS t1
     join INFORMATION_SCHEMA.COLUMNS t2 on t2.Column_Name = t1.Column_Name and t2.TABLE_NAME = 'DATA_PMT_PATIENTS_HISTORY'
     WHERE t1.TABLE_NAME = 'Patients'
          and t1.Column_Name not like 'KRN_%'
          and t1.Column_Name not in ('MODIFY_DATE_TIME')
          and t1.Column_Name not in ('DERN_CONS')
     for xml path('')
), 1, 1, '')
declare Curs cursor fast_forward for
select Patients_ID
from inserted
open Curs
fetch Curs into @PATIENTID
while @@FETCH_STATUS = 0
begin
     set @LAST_NLINE = isnull((select max(N_LINE) from DATA_PMT_PATIENTS_HISTORY where Patients_ID = @PATIENTID), 0)
     -- создаем запись в истории
     exec up_get_id  @KEYNAME = 'DATA_PMT_PATIENTS_HISTORY', @SHIFT = 1, @ID = @ID output
     set @SQL = 'insert into DATA_PMT_PATIENTS_HISTORY ( DATA_PMT_PATIENTS_HISTORY_ID,N_LINE, KRN_CREATE_DATE, KRN_CREATE_USER_ID, ' + @FIELDS + ')
     select ' 
          + cast(@ID as varchar(20))
          + ',' + cast(@LAST_NLINE + 1 as varchar(20))
          + ',' + @NOW
          + ',' + case when @USER_ID is null then 'null' else cast(@USER_ID as varchar(20)) end
          + ',' + @FIELDS + '
     from dbo.Patients where Patients_ID = ' + cast(@PATIENTID as varchar(20))
     --     print @SQL
     exec (@SQL)
          -- создание и запись списка измененных полей
     declare @CURR_FIELD varchar(max), @CHI int, @SPISOK_IZM_POLEY varchar(max), @SQL2 Nvarchar(max), @FLAG bit
     set @SPISOK_IZM_POLEY=''
     while len(@FIELDS)>0
     begin
          set @CHI = charindex(',',@FIELDS)
          IF @CHI = 0
          BEGIN
               set @CURR_FIELD = @FIELDS
               set @FIELDS=''
          END
          ELSE 
          BEGIN
               set @CURR_FIELD = substring(@FIELDS,1,@CHI-1)
               set @FIELDS = ltrim(substring(@FIELDS,@CHI+1, len(@FIELDS) - @CHI))
          END
          set @SQL2= N'IF UPDATE('+@CURR_FIELD+')
               begin
               set  @SPISOK_IZM_POLEY=(
                         case 
                              when @SPISOK_IZM_POLEY='''' then @CURR_FIELD
                              when @SPISOK_IZM_POLEY<>'''' then @SPISOK_IZM_POLEY+'', ''+@CURR_FIELD
                         end)
               end'
          exec sp_executesql @SQL2, N'@SPISOK_IZM_POLEY bit out, @CURR_FIELD varchar(max)', @SPISOK_IZM_POLEY=@SPISOK_IZM_POLEY out, @CURR_FIELD=@CURR_FIELD
     end
     update DATA_PMT_PATIENTS_HISTORY set Patients_hisory_modify_list=@SPISOK_IZM_POLEY where DATA_PMT_PATIENTS_HISTORY_id=@ID
     --     
     fetch curs into @PATIENTID
end
close Curs
deallocate Curs
19 сен 11, 10:50    [11296581]     Ответить | Цитировать Сообщить модератору
 Re: конструкция IF UPDATE(поле) в триггере  [new]
Glory
Member

Откуда:
Сообщений: 104751
nerv
нет, в триггере - курсор, в котором список полей... вот кусок кода:

Еще раз - функцию UPDATE() запрещено использовать за пределами триггера
А не внутри курсора
19 сен 11, 10:54    [11296607]     Ответить | Цитировать Сообщить модератору
 Re: конструкция IF UPDATE(поле) в триггере  [new]
nerv
Member

Откуда:
Сообщений: 734
это то понятно, но даже в теле триггера нельзя использовать конструкцию:
IF UPDATE (@имена_полей)

где @имена_полей - строковая переменная, значение которой формируется в теле триггера
19 сен 11, 10:57    [11296624]     Ответить | Цитировать Сообщить модератору
 Re: конструкция IF UPDATE(поле) в триггере  [new]
Glory
Member

Откуда:
Сообщений: 104751
nerv
это то понятно, но даже в теле триггера нельзя использовать конструкцию:
IF UPDATE (@имена_полей)

И это тоже документировано
19 сен 11, 10:59    [11296630]     Ответить | Цитировать Сообщить модератору
 Re: конструкция IF UPDATE(поле) в триггере  [new]
Glory
Member

Откуда:
Сообщений: 104751
А битовая маска изменямых командой полей и так доступна в COLUMNS_UPDATED ( )
19 сен 11, 11:01    [11296641]     Ответить | Цитировать Сообщить модератору
 Re: конструкция IF UPDATE(поле) в триггере  [new]
nerv
Member

Откуда:
Сообщений: 734
мне нужно список всех полей, исключив несколько, которые будут изменяться всегда (кто создал / отредактировал запись, дату создания и редактирования - эти поля надо исключить)
19 сен 11, 11:03    [11296649]     Ответить | Цитировать Сообщить модератору
 Re: конструкция IF UPDATE(поле) в триггере  [new]
iap
Member

Откуда: Москва
Сообщений: 47142
nerv
это то понятно, но даже в теле триггера нельзя использовать конструкцию:
IF UPDATE (@имена_полей)

где @имена_полей - строковая переменная, значение которой формируется в теле триггера
Скажу Вам больше:
выбросив функцию UPDATE() вообще куда-нибудь подальше,
Вы ничего не потеряете! Так что не надо париться!

Динамический же SQL в триггере плох уже тем, что Вы теряете
возможность прямого доступа к псевдотаблицам inserted и deleted.
Их, стало быть, придётся копировать во временные таблицы. О, ужас!!
19 сен 11, 11:04    [11296658]     Ответить | Цитировать Сообщить модератору
 Re: конструкция IF UPDATE(поле) в триггере  [new]
nerv
Member

Откуда:
Сообщений: 734
в последующем поля могут быть добавлены в таблицу, чтобы триггер не переписывать...
19 сен 11, 11:08    [11296680]     Ответить | Цитировать Сообщить модератору
 Re: конструкция IF UPDATE(поле) в триггере  [new]
мототриггер
Guest
nerv
в последующем поля могут быть добавлены в таблицу, чтобы триггер не переписывать...

называется кодогенерация.
не в триггере динамический sql формировать, а весь триггер перегенеривать. для кастомных специфических триггеров не применимо (с оговоркой что перегенеривать можно не целиком, только помеченный блок), для шаблонных - только так и надо.
19 сен 11, 12:38    [11297464]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить